@sema-agent/server 7.136.0 → 7.138.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 +501 -139
- package/README.md +1 -0
- package/README.zh-CN.md +1 -0
- package/USAGE.md +149 -34
- package/deploy/sema-up/README.md +14 -0
- package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +7 -1
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +7 -1
- package/dist/approval-card.d.ts +21 -14
- package/dist/approval-card.js +1 -0
- package/dist/approval-content-kind.d.ts +6 -0
- package/dist/approval-content-kind.js +7 -0
- package/dist/approval-gate-currency.d.ts +48 -6
- package/dist/approval-gate-currency.js +16 -9
- package/dist/approval-hmac.d.ts +13 -1
- package/dist/approval-hmac.js +1 -1
- package/dist/approval.js +3 -3
- package/dist/audit.js +1 -0
- package/dist/auth-bridge.js +2 -2
- package/dist/background-agent-name.d.ts +5 -0
- package/dist/background-agent-name.js +5 -0
- package/dist/boot/budget-tracing.d.ts +1 -12
- package/dist/boot/deployment-mods.d.ts +46 -16
- package/dist/boot/deployment-mods.js +82 -6
- package/dist/boot/execution-env.d.ts +24 -1
- package/dist/boot/execution-env.js +69 -6
- package/dist/boot/governance-seams.d.ts +10 -17
- package/dist/boot/governance-seams.js +5 -17
- package/dist/boot/leader.d.ts +3 -0
- package/dist/boot/leader.js +1 -0
- package/dist/boot/org-delivery.js +15 -2
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +15 -1
- package/dist/boot/resolve-spec.d.ts +7 -0
- package/dist/boot/resolve-spec.js +36 -26
- package/dist/boot/retention-lane.d.ts +11 -5
- package/dist/boot/retention-lane.js +2 -2
- package/dist/boot/runner-deps.d.ts +7 -3
- package/dist/boot/runner-deps.js +1 -0
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-04-stores.d.ts +2 -13
- package/dist/boot/stage-05-execution-env.d.ts +6 -13
- package/dist/boot/stage-05-execution-env.js +17 -5
- package/dist/boot/stage-06-runners.d.ts +6 -13
- package/dist/boot/stage-06-runners.js +10 -3
- package/dist/boot/stage-07-capability-layer.d.ts +7 -13
- package/dist/boot/stage-07-capability-layer.js +3 -3
- package/dist/boot/stage-08-reapers.d.ts +7 -13
- package/dist/boot/stage-08-reapers.js +2 -1
- package/dist/boot/stage-09-leader.d.ts +7 -13
- package/dist/boot/stage-09-leader.js +2 -2
- package/dist/boot/stage-10-http-server.d.ts +7 -13
- package/dist/boot/stage-10-http-server.js +6 -3
- package/dist/boot/stores.d.ts +1 -1
- package/dist/boot/web-admin.d.ts +5 -2
- package/dist/boot/web-admin.js +3 -3
- package/dist/brain.js +5 -5
- package/dist/broker/broker.d.ts +89 -0
- package/dist/broker/broker.js +287 -0
- package/dist/broker/constants.d.ts +39 -0
- package/dist/broker/constants.js +15 -0
- package/dist/broker/http1.d.ts +111 -0
- package/dist/broker/http1.js +256 -0
- package/dist/broker/lease-book.d.ts +87 -0
- package/dist/broker/lease-book.js +142 -0
- package/dist/broker/lease-file.d.ts +60 -0
- package/dist/broker/lease-file.js +127 -0
- package/dist/broker/main.d.ts +2 -0
- package/dist/broker/main.js +20 -0
- package/dist/budget.d.ts +17 -15
- package/dist/budget.js +2 -2
- package/dist/capabilities/composite-members.d.ts +2 -1
- package/dist/capabilities/composite-members.js +2 -1
- package/dist/capabilities/engine-capabilities.js +1 -0
- package/dist/capabilities/mcp-probe.d.ts +36 -11
- package/dist/capabilities/mcp-probe.js +44 -5
- package/dist/capabilities/scenarios.d.ts +23 -8
- package/dist/capabilities/scenarios.js +13 -8
- package/dist/capabilities/skills.d.ts +28 -5
- package/dist/capabilities/skills.js +8 -0
- package/dist/capability-facts.d.ts +6 -0
- package/dist/capability-facts.js +5 -0
- package/dist/center-credential-renewer.js +5 -1
- package/dist/checkpoint-ctx-seal-m28.d.ts +3 -10
- package/dist/checkpoint-ctx-seal-m28.js +1 -1
- package/dist/checkpoint-identity.d.ts +13 -6
- package/dist/config-catalog.js +16 -7
- package/dist/config-types.d.ts +24 -7
- package/dist/config.d.ts +1 -1
- package/dist/config.js +42 -13
- package/dist/deployment-governance.d.ts +2 -2
- package/dist/deployment-governance.js +7 -9
- package/dist/deployment-shape.d.ts +6 -6
- package/dist/device-ws-protocol.d.ts +1 -0
- package/dist/device-ws-protocol.js +2 -1
- package/dist/file-history-disclosure.d.ts +4 -2
- package/dist/file-history-disclosure.js +2 -0
- package/dist/gate-settlement.d.ts +71 -0
- package/dist/gate-settlement.js +40 -0
- package/dist/hooks/classic-stations.d.ts +12 -54
- package/dist/hooks/classic-stations.js +1 -0
- package/dist/hooks/command-spawn.d.ts +2 -2
- package/dist/hooks/hook-runner.js +14 -14
- package/dist/http/admission.js +14 -9
- package/dist/http/approval-sweeps.js +4 -3
- package/dist/http/caller-trust.d.ts +2 -1
- package/dist/http/caller-trust.js +1 -3
- package/dist/http/checkpoint-ctx.d.ts +48 -7
- package/dist/http/checkpoint-ctx.js +40 -0
- package/dist/http/dispatch.d.ts +4 -0
- package/dist/http/dispatch.js +18 -10
- package/dist/http/durable-run-leg.d.ts +5 -1
- package/dist/http/durable-run-leg.js +5 -3
- package/dist/http/health-self-report.d.ts +2 -2
- package/dist/http/memory-compliance-failure-reply.js +3 -0
- package/dist/http/principal-gate.d.ts +15 -10
- package/dist/http/principal-gate.js +48 -9
- package/dist/http/resume-legs.d.ts +7 -31
- package/dist/http/resume-legs.js +185 -126
- package/dist/http/route-ctx.d.ts +38 -53
- package/dist/http/route-ctx.js +2 -5
- package/dist/http/routes/a2a-serve.js +10 -4
- package/dist/http/routes/agents-roster.d.ts +1 -1
- package/dist/http/routes/agents-roster.js +5 -1
- package/dist/http/routes/approvals-assistant.js +24 -10
- package/dist/http/routes/capabilities.js +23 -11
- package/dist/http/routes/mcp-reconnect.d.ts +3 -2
- package/dist/http/routes/mcp-reconnect.js +7 -7
- package/dist/http/routes/memory-consolidation.d.ts +1 -1
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/rules.js +3 -3
- package/dist/http/routes/runs.js +13 -8
- package/dist/http/routes/session-sync.js +42 -6
- package/dist/http/routes/sessions.js +6 -3
- package/dist/http/routes/side-query.js +2 -3
- package/dist/http/routes/tasks.js +794 -780
- package/dist/http/server.d.ts +35 -25
- package/dist/http/stored-body-replay.d.ts +3 -3
- package/dist/http/stored-body-replay.js +6 -1
- package/dist/http/wire-types.d.ts +66 -33
- package/dist/identity-source.d.ts +65 -0
- package/dist/identity-source.js +45 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/leader/wire.d.ts +7 -0
- package/dist/leader/wire.js +5 -4
- package/dist/mcp-assertion-header.d.ts +51 -40
- package/dist/mcp-assertion-header.js +10 -11
- package/dist/mcp-authorization-face.d.ts +27 -0
- package/dist/mcp-authorization-face.js +15 -0
- package/dist/memory-operator-faces.d.ts +13 -4
- package/dist/memory-operator-faces.js +1 -17
- package/dist/memory-store-refusal.d.ts +3 -3
- package/dist/memory-sync-client.js +72 -57
- package/dist/memory-sync.d.ts +1 -1
- package/dist/model-entry-refusal.d.ts +2 -0
- package/dist/model-entry-refusal.js +11 -0
- package/dist/model-route-gap.d.ts +6 -22
- package/dist/model-route-gap.js +7 -5
- package/dist/model-select.d.ts +6 -17
- package/dist/model-select.js +0 -3
- package/dist/mods-declaration.d.ts +110 -0
- package/dist/mods-declaration.js +109 -0
- package/dist/namespaced-rule-name.d.ts +1 -1
- package/dist/observability/err-text.d.ts +5 -0
- package/dist/observability/err-text.js +9 -0
- package/dist/observability/fail-open.d.ts +17 -1
- package/dist/observability/fail-open.js +17 -1
- package/dist/observability/metrics.js +1 -1
- package/dist/observability/run-terminal.js +1 -0
- package/dist/observability/secret-env-scrub.d.ts +1 -1
- package/dist/observability/secret-env-scrub.js +1 -1
- package/dist/operator-ask.d.ts +2 -2
- package/dist/org-delivery-gate.js +1 -1
- package/dist/org-memory-admission.d.ts +2 -2
- package/dist/org-memory-admission.js +39 -2
- package/dist/parked-decide.d.ts +15 -2
- package/dist/parked-decide.js +17 -10
- package/dist/peer-directory.js +2 -0
- package/dist/peer-seat.d.ts +150 -0
- package/dist/peer-seat.js +239 -0
- package/dist/permission-rule-list.d.ts +2 -2
- package/dist/permission-rule-vocab.d.ts +7 -7
- package/dist/permission-rule-vocab.js +3 -3
- package/dist/plain-string-record.d.ts +38 -0
- package/dist/plain-string-record.js +38 -0
- package/dist/plugins/background-agent-store-sql.js +6 -3
- package/dist/plugins/caching-session-store.d.ts +5 -0
- package/dist/plugins/caching-session-store.js +6 -0
- package/dist/plugins/checkpoint-store-sql.d.ts +34 -29
- package/dist/plugins/checkpoint-store-sql.js +14 -14
- package/dist/plugins/file-history-store-sql.js +10 -16
- package/dist/plugins/file-run-store.js +8 -2
- package/dist/plugins/k8s-exec-protocol.d.ts +69 -13
- package/dist/plugins/k8s-exec-protocol.js +116 -28
- package/dist/plugins/k8s-pod-delete-failure.d.ts +25 -0
- package/dist/plugins/k8s-pod-delete-failure.js +17 -0
- package/dist/plugins/k8s-pod-reaper.d.ts +106 -0
- package/dist/plugins/k8s-pod-reaper.js +122 -0
- package/dist/plugins/local-checkpoint-store.d.ts +4 -17
- package/dist/plugins/local-checkpoint-store.js +3 -4
- package/dist/plugins/local-session-store.d.ts +66 -27
- package/dist/plugins/local-session-store.js +60 -28
- package/dist/plugins/mailbox-store-sql.d.ts +11 -3
- package/dist/plugins/mailbox-store-sql.js +103 -15
- package/dist/plugins/memory-run-store.js +2 -0
- package/dist/plugins/memory-sync-store-pg.d.ts +16 -5
- package/dist/plugins/memory-sync-store-tidb.d.ts +3 -3
- package/dist/plugins/one-time-migrations.d.ts +34 -12
- package/dist/plugins/one-time-migrations.js +51 -9
- package/dist/plugins/permission-rule-store-file.js +2 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +17 -17
- package/dist/plugins/permission-rule-store-sql.js +37 -30
- package/dist/plugins/pg-pool.js +4 -0
- package/dist/plugins/pg-session-storage.d.ts +10 -2
- package/dist/plugins/pg-session-storage.js +20 -7
- package/dist/plugins/remote-env-adb.d.ts +6 -1
- package/dist/plugins/remote-env-adb.js +2 -1
- package/dist/plugins/remote-env-device.d.ts +6 -1
- package/dist/plugins/remote-env-device.js +5 -1
- package/dist/plugins/remote-env-e2b.d.ts +5 -0
- package/dist/plugins/remote-env-e2b.js +2 -1
- package/dist/plugins/remote-env-file-error.d.ts +8 -1
- package/dist/plugins/remote-env-file-error.js +7 -1
- package/dist/plugins/remote-env-host.d.ts +10 -2
- package/dist/plugins/remote-env-host.js +8 -2
- package/dist/plugins/remote-env-k8s.d.ts +140 -11
- package/dist/plugins/remote-env-k8s.js +277 -15
- package/dist/plugins/remote-env-local-docker.d.ts +5 -0
- package/dist/plugins/remote-env-local-docker.js +2 -1
- package/dist/plugins/remote-env-ssh.d.ts +6 -1
- package/dist/plugins/remote-env-ssh.js +2 -1
- package/dist/plugins/retention-store-sql.d.ts +14 -2
- package/dist/plugins/retention-store-sql.js +6 -0
- package/dist/plugins/run-store-sql.js +10 -4
- package/dist/plugins/session-fork.d.ts +10 -13
- package/dist/plugins/session-fork.js +5 -25
- package/dist/plugins/session-ownership.d.ts +24 -3
- package/dist/plugins/session-ownership.js +24 -5
- package/dist/plugins/session-workspace-cell.d.ts +17 -0
- package/dist/plugins/session-workspace-cell.js +38 -0
- package/dist/plugins/sql-errors.d.ts +23 -2
- package/dist/plugins/sql-errors.js +15 -0
- package/dist/plugins/store-backend.js +7 -7
- package/dist/plugins/store-contracts.d.ts +10 -1
- package/dist/plugins/store-fault.d.ts +2 -2
- package/dist/plugins/store-fault.js +4 -2
- package/dist/plugins/tidb-pool.js +13 -0
- package/dist/plugins/tidb-session-store.d.ts +17 -2
- package/dist/plugins/tidb-session-store.js +18 -7
- package/dist/plugins/tool-result-store-sql.d.ts +13 -6
- package/dist/plugins/tool-result-store-sql.js +8 -7
- package/dist/plugins/worktree-isolation.d.ts +3 -2
- package/dist/plugins/worktree-isolation.js +1 -7
- package/dist/project-identity.d.ts +1 -14
- package/dist/project-identity.js +0 -4
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +31 -2
- package/dist/request-value-closure.js +7 -1
- package/dist/rule-entry-list.d.ts +3 -2
- package/dist/rule-entry-list.js +2 -2
- package/dist/rules-consent.js +12 -7
- package/dist/run-local.d.ts +2 -2
- package/dist/run-local.js +12 -6
- package/dist/runs.d.ts +7 -1
- package/dist/runs.js +8 -2
- package/dist/runtime-governance.d.ts +5 -5
- package/dist/sandbox-git-lease.d.ts +49 -0
- package/dist/sandbox-git-lease.js +60 -0
- package/dist/sandbox-git-plane.d.ts +84 -0
- package/dist/sandbox-git-plane.js +105 -0
- package/dist/security.d.ts +16 -4
- package/dist/security.js +8 -3
- package/dist/server-secret-env.d.ts +12 -3
- package/dist/server-secret-env.js +18 -2
- package/dist/session-error-wire.d.ts +14 -6
- package/dist/session-error-wire.js +2 -1
- package/dist/session-incarnation.d.ts +4 -5
- package/dist/session-incarnation.js +2 -2
- package/dist/session-policy-wire.d.ts +1 -1
- package/dist/session-policy-wire.js +2 -2
- package/dist/session-sync.d.ts +1 -1
- package/dist/session-workspace.d.ts +130 -0
- package/dist/session-workspace.js +83 -0
- package/dist/spec-fields.d.ts +44 -14
- package/dist/spec-fields.js +33 -12
- package/dist/standing-answer-grant.d.ts +2 -13
- package/dist/standing-answer-grant.js +0 -7
- package/dist/stored-request-prompt-profile-m30.d.ts +49 -0
- package/dist/stored-request-prompt-profile-m30.js +25 -0
- package/dist/task-a2a.d.ts +44 -14
- package/dist/task-a2a.js +46 -20
- package/dist/task-mcp.d.ts +34 -21
- package/dist/task-mcp.js +46 -22
- package/dist/task-settings.d.ts +2 -2
- package/dist/tool-approval.d.ts +43 -9
- package/dist/tool-approval.js +57 -15
- package/dist/tool-rule-names.d.ts +5 -0
- package/dist/trace/core-keyset-guard.d.ts +34 -19
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +4 -0
- package/dist/trace/exit-seat.d.ts +20 -1
- package/dist/trace/exit-seat.js +5 -2
- package/dist/trace/extension-call-face.d.ts +33 -0
- package/dist/trace/extension-call-face.js +39 -0
- package/dist/trace/ledger-sink.d.ts +4 -5
- package/dist/trace/ledger-sink.js +3 -7
- package/dist/trace/project.d.ts +62 -10
- package/dist/trace/project.js +49 -9
- package/dist/trace/redact.d.ts +18 -6
- package/dist/trace/redact.js +154 -60
- package/dist/trace/self-minted-wire.d.ts +500 -7
- package/dist/trace/self-minted-wire.js +182 -1
- package/dist/trace/wire-projection-faces.d.ts +7 -5
- package/dist/trace/wire-projection-faces.js +9 -4
- package/dist/user-authored-text.d.ts +2 -2
- package/dist/user-authored-text.js +16 -1
- package/dist/web-admin-client/apply-effective.js +0 -1
- package/dist/web-admin-client/center-request.d.ts +23 -4
- package/dist/web-admin-client/center-request.js +42 -8
- package/dist/web-admin-client/http-client.js +6 -6
- package/dist/web-admin-client/skills-mcp.d.ts +8 -4
- package/dist/web-admin-client/skills-mcp.js +31 -18
- package/dist/web-admin-client/types.d.ts +10 -5
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +11 -5
- package/package.json +3 -3
- package/wire-changes/server@7.137.0.json +825 -0
- package/wire-changes/server@7.138.0.json +446 -0
|
@@ -1,31 +1,61 @@
|
|
|
1
|
+
import { type EngineDollar, type ModAdmissionRecord, type ModRegistration } from "@sema-agent/core";
|
|
2
|
+
import { type ModsDeclaration } from "../mods-declaration.js";
|
|
3
|
+
import type { Logger } from "../observability/logger.js";
|
|
4
|
+
import type { Metrics } from "../observability/metrics.js";
|
|
1
5
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* 起服自证(律三:拒形只有引擎一种读法,本仓只负责「不写」与「启动时自证」):
|
|
5
|
-
* 部署座上的注册是本仓自己铸的。它们坏了
|
|
6
|
-
* —— 坏名、坏档、缺 `uses.calls`、`on` 越出 `uses`、只选无站的名字、`register` 抛 —— 引擎在每条腿的 prepare 里拒
|
|
7
|
-
* (`config.mods_invalid`),那就是每个请求都失败。所以起服时让引擎的 admission 判一次:判官仍是引擎(`admitModChain`),
|
|
8
|
-
* 本函数不判形,只把它的拒折成一句起服错误、拒启。两个起服入口(server 第五段、本地 CLI)同调这一只。
|
|
6
|
+
* 部署座注册的**出处标签**(谁供的这张注册)—— 宿主自己的词,引擎原样携带、不判;**全仓唯一写点**。
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* ·
|
|
13
|
-
*
|
|
8
|
+
* `wiring_manifest.mods[]` 的一行上有两个词字段,各自一张闭集、互不相交:`seat` 是引擎的座词(`MOD_SEATS`:`deployment` | `task`,这张注册站在哪一座),
|
|
9
|
+
* `provenance` 是这张表的值(这张注册是谁供的)。两个字段不共用词 —— 同一个词不在一行里指两件事。
|
|
10
|
+
* · `minted` → `server`:本服务自己铸的(拒绝计量 / 工具追踪 / 品牌行);
|
|
11
|
+
* · `declared` → `operator`:运维在部署声明(`MODS_ROOT` / `MODS_PACKAGES`)里点名装进来的包。词取「谁供的」:与 `server` 同一个维度(供给方),
|
|
12
|
+
* 并沿用本仓对这件事的既有称呼「运维声明」。不用 `deployment`:它是座词,同一行上同形不同义。
|
|
13
|
+
* 加一种供给方 = 在这里加一行;取到的词与座词相交 ⇒ 下面的类型门编译红。
|
|
14
14
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
export declare const MOD_PROVENANCE: {
|
|
16
|
+
readonly minted: "server";
|
|
17
|
+
readonly declared: "operator";
|
|
18
|
+
};
|
|
18
19
|
/**
|
|
19
|
-
*
|
|
20
|
+
* 本仓自铸的部署注册 —— 哪几张、什么顺序只写在这里(装配口 {@link assembleDeploymentMods} 把它们排在声明的包之前):
|
|
20
21
|
* · 拒绝计量恒挂、在前;工具追踪(`TOOL_TRACE=true`,交 `traceLogger`)在后。两张都是 `prepend` 档的观察者,引擎按「档 → 部署先于任务 → 座内顺序」
|
|
21
22
|
* 串行跑观察者、且都在链之前 ⇒ 同一次拒绝先计数、后写追踪行;
|
|
22
23
|
* · 品牌行(`brandIdentity`:品牌部署 = local / TOC)—— `prompt.compose` 上的一条部署类 overlay(`capabilities/brand-identity.ts`),与两只观察者
|
|
23
24
|
* 不在同一个事件上,顺序不影响它们。部署开不开品牌只在这一个入参表态。
|
|
25
|
+
* 出处标签:自铸的每一张都带宿主标签 {@link MOD_PROVENANCE}`.minted`,声明的包由装配口给 `.declared` —— 引擎把宿主给的标签原样记进准入记录与每条腿的
|
|
26
|
+
* `wiring_manifest.mods[]`,一条腿的部署座由此分得出「本服务自铸」与「运维声明」两种来源。
|
|
24
27
|
*/
|
|
25
28
|
export declare function createDeploymentMods(input: {
|
|
26
29
|
readonly metrics: Pick<Metrics, "inc">;
|
|
27
30
|
readonly traceLogger?: Logger | undefined;
|
|
28
31
|
readonly brandIdentity?: boolean | undefined;
|
|
29
32
|
}): readonly ModRegistration<EngineDollar>[];
|
|
30
|
-
|
|
33
|
+
/** 起服装上的一只声明包(起服日志行 `mods_package_loaded` 与 `/health` / `/v1/capabilities` 的读数都读这一份)。 */
|
|
34
|
+
export interface LoadedModPackage {
|
|
35
|
+
readonly name: string;
|
|
36
|
+
/** 引擎准入记录里这只包站的档(准入判过的那一份,不是声明里写的)。 */
|
|
37
|
+
readonly tier: ModAdmissionRecord["tier"];
|
|
38
|
+
/** 读包者按相等判过的引擎契约号(包声明的 `contract` 与引擎的 `KERNEL_CONTRACT_VERSION` 相等才装得上)。 */
|
|
39
|
+
readonly contract: number;
|
|
40
|
+
/** 读包者交回的三件字节摘要(`ModPackageRegistration.digest`,按给值记)—— 认得出「装的是哪几份字节」,不是代码完整性凭据。 */
|
|
41
|
+
readonly digest: string;
|
|
42
|
+
}
|
|
43
|
+
/** 装配的结果:部署座的注册(自铸在前、声明在后,整列已过引擎准入)与装上的声明包(只数声明的包,自铸的不算)。 */
|
|
44
|
+
export interface DeploymentModsAssembly {
|
|
45
|
+
readonly registrations: readonly ModRegistration<EngineDollar>[];
|
|
46
|
+
readonly loaded: readonly LoadedModPackage[];
|
|
47
|
+
}
|
|
48
|
+
/** 部署座的唯一装配口(两只起服入口同调;三段与失败见文件头注)。 */
|
|
49
|
+
export declare function assembleDeploymentMods(input: {
|
|
50
|
+
readonly metrics: Pick<Metrics, "inc">;
|
|
51
|
+
readonly traceLogger?: Logger | undefined;
|
|
52
|
+
readonly brandIdentity?: boolean | undefined;
|
|
53
|
+
readonly declaration: ModsDeclaration;
|
|
54
|
+
readonly logger: Pick<Logger, "info">;
|
|
55
|
+
}): Promise<DeploymentModsAssembly>;
|
|
56
|
+
/**
|
|
57
|
+
* 第三段:整列交引擎准入判一次(判官是引擎;本函数不判形,只把它的拒、报告与判拒折成一句 `admission_refused`)。
|
|
58
|
+
* 过了 ⇒ 交回这一次准入的记录(每张注册一行,全部挂上了 —— 有一行被判拒就不会走到这里)。
|
|
59
|
+
*/
|
|
60
|
+
export declare function assertDeploymentModsAdmitted(mods: readonly ModRegistration<EngineDollar>[]): Promise<readonly ModAdmissionRecord[]>;
|
|
31
61
|
//# sourceMappingURL=deployment-mods.d.ts.map
|
|
@@ -1,26 +1,102 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { realpathSync, statSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, relative, sep } from "node:path";
|
|
3
|
+
import { admitModChain, KERNEL_CONTRACT_VERSION, loadModPackage } from "@sema-agent/core";
|
|
2
4
|
import { createBrandIdentityRegistration } from "../capabilities/brand-identity.js";
|
|
3
5
|
import { createPermissionDeniedMeter, createToolTracer } from "../observability/tool-trace.js";
|
|
6
|
+
import { errorCodeOf, errorText } from "../observability/err-text.js";
|
|
7
|
+
import { sanitizeWireText } from "../trace/engine-notice-wire.js";
|
|
8
|
+
import { DeploymentModsRefusedError } from "../mods-declaration.js";
|
|
9
|
+
export const MOD_PROVENANCE = { minted: "server", declared: "operator" };
|
|
4
10
|
export function createDeploymentMods(input) {
|
|
5
11
|
return [
|
|
6
12
|
createPermissionDeniedMeter(input.metrics),
|
|
7
13
|
...(input.traceLogger !== undefined ? [createToolTracer(input.traceLogger)] : []),
|
|
8
14
|
...(input.brandIdentity === true ? [createBrandIdentityRegistration()] : []),
|
|
9
|
-
];
|
|
15
|
+
].map((registration) => ({ ...registration, provenance: MOD_PROVENANCE.minted }));
|
|
16
|
+
}
|
|
17
|
+
export async function assembleDeploymentMods(input) {
|
|
18
|
+
const minted = createDeploymentMods(input);
|
|
19
|
+
const resolved = resolveDeclaredPackages(input.declaration);
|
|
20
|
+
const declared = [];
|
|
21
|
+
for (const { pkg, realDir } of resolved)
|
|
22
|
+
declared.push(await loadDeclaredPackage(pkg, realDir));
|
|
23
|
+
const registrations = [...minted, ...declared];
|
|
24
|
+
const records = await assertDeploymentModsAdmitted(registrations);
|
|
25
|
+
const loaded = resolved.map(({ pkg }, i) => ({ name: pkg.name, tier: admittedRecordOf(records, pkg.name).tier, contract: KERNEL_CONTRACT_VERSION, digest: declared[i].digest }));
|
|
26
|
+
for (const row of loaded)
|
|
27
|
+
input.logger.info("mods_package_loaded", { name: sanitizeWireText(row.name), tier: row.tier, contract: row.contract, digest: row.digest });
|
|
28
|
+
return { registrations, loaded };
|
|
29
|
+
}
|
|
30
|
+
function fsCauseOf(e) {
|
|
31
|
+
const code = errorCodeOf(e);
|
|
32
|
+
return typeof code === "string" && /^E[A-Z0-9]{1,31}$/.test(code) ? code : "unknown";
|
|
33
|
+
}
|
|
34
|
+
function strictlyUnderRoot(root, child) {
|
|
35
|
+
const rel = relative(root, child);
|
|
36
|
+
return rel !== "" && rel.split(sep)[0] !== ".." && !isAbsolute(rel);
|
|
37
|
+
}
|
|
38
|
+
function resolveDeclaredPackages(declaration) {
|
|
39
|
+
if (declaration.packages === undefined)
|
|
40
|
+
return [];
|
|
41
|
+
let realRoot;
|
|
42
|
+
try {
|
|
43
|
+
realRoot = realpathSync(declaration.root);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
throw new DeploymentModsRefusedError({ word: "root_unreadable", cause: fsCauseOf(e) });
|
|
47
|
+
}
|
|
48
|
+
return declaration.packages.map((pkg, entry) => {
|
|
49
|
+
let realDir;
|
|
50
|
+
let isDirectory;
|
|
51
|
+
try {
|
|
52
|
+
realDir = realpathSync(pkg.dir);
|
|
53
|
+
isDirectory = statSync(realDir).isDirectory();
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
throw new DeploymentModsRefusedError({ word: "dir_unreadable", entry, cause: fsCauseOf(e) });
|
|
57
|
+
}
|
|
58
|
+
if (!strictlyUnderRoot(realRoot, realDir))
|
|
59
|
+
throw new DeploymentModsRefusedError({ word: "outside_root", entry });
|
|
60
|
+
if (!isDirectory)
|
|
61
|
+
throw new DeploymentModsRefusedError({ word: "not_a_directory", entry });
|
|
62
|
+
return { pkg, realDir };
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function machineCodeOf(e) {
|
|
66
|
+
const code = errorCodeOf(e);
|
|
67
|
+
return typeof code === "string" && /^[A-Za-z][A-Za-z0-9_.-]{0,63}$/.test(code) ? code : undefined;
|
|
68
|
+
}
|
|
69
|
+
async function loadDeclaredPackage(pkg, realDir) {
|
|
70
|
+
let registration;
|
|
71
|
+
try {
|
|
72
|
+
registration = await loadModPackage(realDir, { tier: pkg.tier, provenance: MOD_PROVENANCE.declared, ...("options" in pkg ? { options: pkg.options } : {}) });
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
throw new DeploymentModsRefusedError({ word: "package_refused", name: pkg.name, code: machineCodeOf(e), reason: errorText(e) });
|
|
76
|
+
}
|
|
77
|
+
if (registration.name !== pkg.name)
|
|
78
|
+
throw new DeploymentModsRefusedError({ word: "name_mismatch", name: pkg.name, packageName: registration.name });
|
|
79
|
+
return registration;
|
|
10
80
|
}
|
|
11
|
-
const REFUSED = "deployment extension registration refused";
|
|
12
81
|
export async function assertDeploymentModsAdmitted(mods) {
|
|
13
82
|
const reports = [];
|
|
14
83
|
let records;
|
|
15
84
|
try {
|
|
16
|
-
({ records } = await admitModChain({ deployment: mods }, (err) => void reports.push(err
|
|
85
|
+
({ records } = await admitModChain({ deployment: mods }, (err) => void reports.push(errorText(err))));
|
|
17
86
|
}
|
|
18
87
|
catch (e) {
|
|
19
|
-
throw new
|
|
88
|
+
throw new DeploymentModsRefusedError({ word: "admission_refused", code: machineCodeOf(e), reason: errorText(e) });
|
|
20
89
|
}
|
|
21
90
|
const refused = records.flatMap((r) => ("refusedBy" in r ? [`"${r.name}" refused by ${r.refusedBy}: ${r.reason}`] : []));
|
|
22
91
|
const problems = [...reports, ...refused];
|
|
23
92
|
if (problems.length > 0)
|
|
24
|
-
throw new
|
|
93
|
+
throw new DeploymentModsRefusedError({ word: "admission_refused", code: undefined, reason: problems.join("; ") });
|
|
94
|
+
return records;
|
|
95
|
+
}
|
|
96
|
+
function admittedRecordOf(records, name) {
|
|
97
|
+
const record = records.find((r) => r.seat === "deployment" && r.name === name);
|
|
98
|
+
if (record === undefined)
|
|
99
|
+
throw new DeploymentModsRefusedError({ word: "admission_refused", code: undefined, reason: `the engine's admission returned no record for ${JSON.stringify(name)}` });
|
|
100
|
+
return record;
|
|
25
101
|
}
|
|
26
102
|
//# sourceMappingURL=deployment-mods.js.map
|
|
@@ -7,7 +7,9 @@ import { PerTaskImageRegistry } from "../per-task-image.js";
|
|
|
7
7
|
import type { DeviceEnrollment } from "../device-enrollment.js";
|
|
8
8
|
import type { DeviceStore } from "../device-store.js";
|
|
9
9
|
import type { DeviceWsHub } from "../device-ws-hub.js";
|
|
10
|
-
import { k8sExecutionEnvFactory, type K8sEnvConfig, type K8sEnvDeps } from "../plugins/remote-env-k8s.js";
|
|
10
|
+
import { k8sExecutionEnvFactory, type K8sEnvConfig, type K8sEnvDeps, type SandboxSecretSeat } from "../plugins/remote-env-k8s.js";
|
|
11
|
+
import { type SandboxGitPlane, type SandboxGitRunRows } from "../sandbox-git-plane.js";
|
|
12
|
+
import { type SandboxPodReaper } from "../plugins/k8s-pod-reaper.js";
|
|
11
13
|
import { type SpaceCommitRows } from "../workspace-space-commit.js";
|
|
12
14
|
import * as facts from "../capability-facts.js";
|
|
13
15
|
import { type TaskAttachmentStore } from "../plugins/task-attachment-store.js";
|
|
@@ -76,6 +78,10 @@ export declare function createSessionScopedRegistries(maxEntries?: number): Sess
|
|
|
76
78
|
*/
|
|
77
79
|
export declare function createK8sRunEnvFactory(k8sCfg: K8sEnvConfig, seats: {
|
|
78
80
|
imageOf(sessionId: string): string | undefined;
|
|
81
|
+
/** The member git-credential broker seat for the pod's run (`runId` = the one reading of the run that owns the pod, the same value its
|
|
82
|
+
* `sema.io/run` label carries; `sandbox-git-plane.ts` `sandboxBrokerSeatOf` over the boot's plane reading and the run row's identity);
|
|
83
|
+
* absent seat / `undefined` answer ⇒ the pod carries no broker. */
|
|
84
|
+
brokerSeatOf?(runId: string | undefined): Promise<K8sEnvConfig["sandboxBroker"]>;
|
|
79
85
|
/** The session store's by-id head read (`SessionStore.headOf`, picked once by `headReadOf`); the occupant is its live-occupant projection
|
|
80
86
|
* (`sessionFaceOfHead`). Absent ⇔ the store has none, which `assertWorkspaceSpaceReadable` refuses together with `space` (embeddings that
|
|
81
87
|
* wire another lane pass none). */
|
|
@@ -84,6 +90,17 @@ export declare function createK8sRunEnvFactory(k8sCfg: K8sEnvConfig, seats: {
|
|
|
84
90
|
* or without a store backend — the latter `assertWorkspaceSpaceReadable` refuses together with `space`. */
|
|
85
91
|
spaceCommits(): SpaceCommitRows | undefined;
|
|
86
92
|
}, deps?: K8sEnvDeps): ReturnType<typeof k8sExecutionEnvFactory>;
|
|
93
|
+
/**
|
|
94
|
+
* k8s 车道沙箱秘密座的**起服前提**(装配后的真门,第 5 段 await)。法只有一条:**秘密座非空(`K8S_SANDBOX_ENV` 点到了本进程环境里有的键)⇒
|
|
95
|
+
* 问一次 SelfSubjectAccessReview(env 座那一行动词 {@link SANDBOX_SECRET_SEAT_VERBS}`.env`,沙箱命名空间)** —— 只问这一座自己发的调用,
|
|
96
|
+
* 不问租约座的 `patch`(那一座由凭据平面的判官在它的前提都成立时另问,见 `readSandboxGitPlane`):
|
|
97
|
+
* · 答了「不许」(任一动词)⇒ 拒启,一行拒句点名缺的动词、命名空间、Role 规则原文与出路(`[sandbox-secret-rbac]`)—— 不等第一个 run 才失败;
|
|
98
|
+
* · 问不到(请求失败 / 审查本身被拒 / 答复没有 `status.allowed`)⇒ 照常起服:F 类兜底口 `server.sandbox-secret.seat-unverified` 计数 + 一行
|
|
99
|
+
* `sandbox_secret_seat_unverified`。放行的最坏后果:RBAC 真缺时第一个要建 Secret 的 run 连接即拒(`auth_failed`,pod 被删)—— 秘密值仍然
|
|
100
|
+
* 只经 Secret,不回落明文;
|
|
101
|
+
* · 秘密座空 ⇒ 一个请求都不发(没有 Secret 要建)。
|
|
102
|
+
*/
|
|
103
|
+
export declare function ensureSandboxSecretSeat(k8sCfg: K8sEnvConfig, logger: Pick<Logger, "warn">, deps?: K8sEnvDeps, read?: () => Promise<SandboxSecretSeat>): Promise<void>;
|
|
87
104
|
/**
|
|
88
105
|
* k8s 工作区空间的**起服前提**(装配后的真门;同段先例 = `assertDeviceLaneWired`)。法只有一条:
|
|
89
106
|
* **生效策略 `space`(事实 `workspaceSpace`)∧ {@link createK8sRunEnvFactory} 的两只座缺一 ⇒ 拒启。**
|
|
@@ -119,6 +136,9 @@ export interface ExecutionEnvCtx {
|
|
|
119
136
|
spaceCommits?: () => SpaceCommitRows | undefined;
|
|
120
137
|
/** k8s 工作区空间的住客读:会话店的按 id 读(`headReadOf(sessionStore)`,第 5 段判一次、与起服门同一只)。不传 ⇒ 同上,不开、响亮。 */
|
|
121
138
|
headOf?: HeadRead;
|
|
139
|
+
/** run 店的按 id 读(成员凭据代理座读 run 行上受理时记下的身份元组 `RunRecord.identity`)。取值闭包:run 店第 7 段才绑(`late-binds.ts`),
|
|
140
|
+
* 平面开着时每个 run 的 pod 建起前求值一次。不传 / 答 `undefined`(没有存储后端)⇒ 读不到身份 ⇒ 不挂代理。 */
|
|
141
|
+
runRows?: () => SandboxGitRunRows | undefined;
|
|
122
142
|
}
|
|
123
143
|
export declare function createExecutionEnv(ctx: ExecutionEnvCtx): {
|
|
124
144
|
perTaskImage: PerTaskImageRegistry;
|
|
@@ -134,5 +154,8 @@ export declare function createExecutionEnv(ctx: ExecutionEnvCtx): {
|
|
|
134
154
|
sendUserFileTaskEnvs: TaskEnvRegistry | undefined;
|
|
135
155
|
lspManager: import("@sema-agent/core").NodeLspManager | import("../lsp/manager.js").E2bLspManager | undefined;
|
|
136
156
|
spaceReclaimer: SpaceReclaimer | undefined;
|
|
157
|
+
sandboxSecretSeatGate: (() => Promise<void>) | undefined;
|
|
158
|
+
sandboxPodReaper: SandboxPodReaper | undefined;
|
|
159
|
+
readSandboxGitPlane: () => Promise<SandboxGitPlane>;
|
|
137
160
|
};
|
|
138
161
|
//# sourceMappingURL=execution-env.d.ts.map
|
|
@@ -11,7 +11,11 @@ import { adbExecutionEnvFactory } from "../plugins/remote-env-adb.js";
|
|
|
11
11
|
import { deviceExecutionEnvFactory } from "../plugins/remote-env-device.js";
|
|
12
12
|
import { e2bExecutionEnvFactory } from "../plugins/remote-env-e2b.js";
|
|
13
13
|
import { hostExecutionEnvFactory, RemoteHostExecutionEnv } from "../plugins/remote-env-host.js";
|
|
14
|
-
import { boundedStoreCall, checkSandboxEgressPolicy, createSpaceReclaimer, K8S_SANDBOX_NAMESPACE_DEFAULT, k8sExecutionEnvFactory, rpcTimeoutMsOf } from "../plugins/remote-env-k8s.js";
|
|
14
|
+
import { boundedStoreCall, checkSandboxEgressPolicy, createSandboxPodApi, createSpaceReclaimer, K8S_SANDBOX_NAMESPACE_DEFAULT, k8sExecutionEnvFactory, readSandboxSecretSeat, rpcTimeoutMsOf } from "../plugins/remote-env-k8s.js";
|
|
15
|
+
import { podSpecPatchBrokerRefusal, SANDBOX_SECRET_SEAT_VERBS } from "../plugins/k8s-exec-protocol.js";
|
|
16
|
+
import { judgeSandboxGitPlane, runIdentitySourceOf, sandboxBrokerSeatOf, sandboxGitPlaneAsksSecretSeat, sandboxGitPlanePremisesOf } from "../sandbox-git-plane.js";
|
|
17
|
+
import { createSandboxPodReaper } from "../plugins/k8s-pod-reaper.js";
|
|
18
|
+
import { recordFailOpen } from "../observability/fail-open.js";
|
|
15
19
|
import { createRunWorkspaceSnapshotSeat } from "../fleet/workspace-snapshot-residual.js";
|
|
16
20
|
import { createSpaceCommitFence } from "../workspace-space-commit.js";
|
|
17
21
|
import { localDockerExecutionEnvFactory } from "../plugins/remote-env-local-docker.js";
|
|
@@ -58,7 +62,12 @@ function forwardedSandboxEnvKeys(remoteExec) {
|
|
|
58
62
|
}
|
|
59
63
|
}
|
|
60
64
|
function buildSandboxLaneEnv(config, explicit) {
|
|
61
|
-
const
|
|
65
|
+
const secretEnv = { ...(explicit ?? {}) };
|
|
66
|
+
const env = Object.fromEntries(Object.entries(derivePkgSourceEnv(config.sandboxPkgSource, config.sandboxPkgSourceCustom)).filter(([name]) => !Object.hasOwn(secretEnv, name)));
|
|
67
|
+
return { ...(Object.keys(env).length > 0 ? { env } : {}), ...(Object.keys(secretEnv).length > 0 ? { secretEnv } : {}) };
|
|
68
|
+
}
|
|
69
|
+
function sandboxLaneEnvMerged(lane) {
|
|
70
|
+
const merged = { ...(lane.env ?? {}), ...(lane.secretEnv ?? {}) };
|
|
62
71
|
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
63
72
|
}
|
|
64
73
|
const MAX_CWD_SESSIONS = 4096;
|
|
@@ -118,6 +127,8 @@ export function createK8sRunEnvFactory(k8sCfg, seats, deps) {
|
|
|
118
127
|
const child = ctx.placementRootSessionId !== ctx.sessionId;
|
|
119
128
|
const s3Snapshot = child && k8sCfg.s3Snapshot !== undefined ? spaceOff(k8sCfg.s3Snapshot) : k8sCfg.s3Snapshot;
|
|
120
129
|
const spaceOccupant = child ? undefined : await occupantOf(seats, ctx.sessionId, ctx.taskId, rpcTimeoutMsOf(k8sCfg));
|
|
130
|
+
const runId = !child && ctx.taskId !== undefined ? ctx.taskId : undefined;
|
|
131
|
+
const sandboxBroker = await seats.brokerSeatOf?.(runId);
|
|
121
132
|
const { cache, ...deploymentCfg } = k8sCfg;
|
|
122
133
|
return k8sExecutionEnvFactory({
|
|
123
134
|
...deploymentCfg,
|
|
@@ -125,6 +136,8 @@ export function createK8sRunEnvFactory(k8sCfg, seats, deps) {
|
|
|
125
136
|
...(s3Snapshot !== undefined ? { s3Snapshot } : {}),
|
|
126
137
|
image: seats.imageOf(ctx.sessionId) ?? k8sCfg.image,
|
|
127
138
|
...(spaceOccupant !== undefined ? { spaceOccupant } : {}),
|
|
139
|
+
...(runId !== undefined ? { runId } : {}),
|
|
140
|
+
...(sandboxBroker !== undefined ? { sandboxBroker } : {}),
|
|
128
141
|
onWorkspaceSnapshot,
|
|
129
142
|
}, deps)(ctx);
|
|
130
143
|
};
|
|
@@ -156,6 +169,34 @@ function spaceOff(store) {
|
|
|
156
169
|
const { space: _off, ...parkOnly } = store;
|
|
157
170
|
return parkOnly;
|
|
158
171
|
}
|
|
172
|
+
export async function ensureSandboxSecretSeat(k8sCfg, logger, deps, read = () => readSandboxSecretSeat(k8sCfg, "env", deps)) {
|
|
173
|
+
const names = Object.keys(k8sCfg.podSecretEnv ?? {});
|
|
174
|
+
if (names.length === 0)
|
|
175
|
+
return;
|
|
176
|
+
const namespace = k8sCfg.namespace ?? K8S_SANDBOX_NAMESPACE_DEFAULT;
|
|
177
|
+
const seat = await read();
|
|
178
|
+
switch (seat.state) {
|
|
179
|
+
case "granted":
|
|
180
|
+
return;
|
|
181
|
+
case "denied":
|
|
182
|
+
throw new Error(`K8S_SANDBOX_ENV forwards ${names.length} variable(s) into the k8s sandbox, but this service account may not ${seat.verbs.join(", ")} secrets ` +
|
|
183
|
+
`in namespace ${namespace} [sandbox-secret-rbac]: the forwarded values reach a sandbox pod only through that pod's own Secret (the pod spec carries ` +
|
|
184
|
+
`references, never the values). Add to the sandbox Role in ${namespace}: \`- apiGroups: [""] resources: [secrets] verbs: [${SANDBOX_SECRET_SEAT_VERBS.env.join(", ")}]\` ` +
|
|
185
|
+
"(or unset K8S_SANDBOX_ENV), and restart");
|
|
186
|
+
case "unverified":
|
|
187
|
+
recordFailOpen("server.sandbox-secret.seat-unverified", `namespace=${namespace} ${seat.detail}`);
|
|
188
|
+
logger.warn("sandbox_secret_seat_unverified", {
|
|
189
|
+
namespace,
|
|
190
|
+
detail: seat.detail,
|
|
191
|
+
effect: `the boot could not confirm the sandbox Secret RBAC (secrets ${SANDBOX_SECRET_SEAT_VERBS.env.join(" / ")}) — the service starts; if the Role lacks them, the first run that forwards K8S_SANDBOX_ENV is refused at connect (auth_failed) and its pod deleted — the values never go into the pod spec`,
|
|
192
|
+
});
|
|
193
|
+
return;
|
|
194
|
+
default: {
|
|
195
|
+
const unreachable = seat;
|
|
196
|
+
throw new Error(`unhandled sandbox secret seat reading: ${String(unreachable.state)}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
159
200
|
export function assertWorkspaceSpaceReadable(space, seats, cache, sessionStoreLabel) {
|
|
160
201
|
if (space.available && persistNeedsOccupant(space.policy.persist)) {
|
|
161
202
|
const missing = seats.headOf === undefined ? `the session store (${sessionStoreLabel}) has no by-id occupant read (headOf)`
|
|
@@ -207,6 +248,10 @@ export function createExecutionEnv(ctx) {
|
|
|
207
248
|
const { perSessionInheritEnv, setSessionInheritEnv } = sessionScoped;
|
|
208
249
|
let executionEnvFactory;
|
|
209
250
|
let spaceReclaimer;
|
|
251
|
+
let sandboxSecretSeatGate;
|
|
252
|
+
let sandboxPodReaper;
|
|
253
|
+
const planeCell = {};
|
|
254
|
+
let readSandboxGitPlane = async () => (planeCell.current = judgeSandboxGitPlane(sandboxGitPlanePremisesOf(config, {})));
|
|
210
255
|
let worktreeReap;
|
|
211
256
|
if (config.remoteExec?.provider === "e2b") {
|
|
212
257
|
executionEnvFactory = e2bExecutionEnvFactory({
|
|
@@ -217,7 +262,7 @@ export function createExecutionEnv(ctx) {
|
|
|
217
262
|
...(config.remoteExec.livenessMs != null ? { livenessMs: config.remoteExec.livenessMs } : {}),
|
|
218
263
|
...(config.remoteExec.allowInternetAccess != null ? { allowInternetAccess: config.remoteExec.allowInternetAccess } : {}),
|
|
219
264
|
...(config.remoteExec.mountPath ? { mountPath: config.remoteExec.mountPath } : {}),
|
|
220
|
-
...((env) => (env !== undefined ? { sandboxEnv: env } : {}))(buildSandboxLaneEnv(config, config.remoteExec.sandboxEnv)),
|
|
265
|
+
...((env) => (env !== undefined ? { sandboxEnv: env } : {}))(sandboxLaneEnvMerged(buildSandboxLaneEnv(config, config.remoteExec.sandboxEnv))),
|
|
221
266
|
logger,
|
|
222
267
|
metrics,
|
|
223
268
|
});
|
|
@@ -243,11 +288,29 @@ export function createExecutionEnv(ctx) {
|
|
|
243
288
|
...((f) => (f.available ? { cache: f.cache } : {}))(facts.workspaceCache(config)),
|
|
244
289
|
...(config.remoteExec.workspaceSnapshotExclude ? { snapshotExclude: config.remoteExec.workspaceSnapshotExclude } : {}),
|
|
245
290
|
logger,
|
|
246
|
-
...((
|
|
291
|
+
...((lane) => ({ ...(lane.env !== undefined ? { podEnv: lane.env } : {}), ...(lane.secretEnv !== undefined ? { podSecretEnv: lane.secretEnv } : {}) }))(buildSandboxLaneEnv(config, config.remoteExec.sandboxEnv)),
|
|
247
292
|
};
|
|
248
|
-
|
|
293
|
+
const brokerImage = config.remoteExec.brokerImage;
|
|
294
|
+
executionEnvFactory = createK8sRunEnvFactory(k8sCfg, {
|
|
295
|
+
imageOf: (sid) => perTaskImage.get(sid),
|
|
296
|
+
headOf: ctx.headOf,
|
|
297
|
+
spaceCommits: ctx.spaceCommits ?? (() => undefined),
|
|
298
|
+
brokerSeatOf: async (runId) => {
|
|
299
|
+
const plane = planeCell.current;
|
|
300
|
+
if (plane === undefined || plane.state !== "on")
|
|
301
|
+
return undefined;
|
|
302
|
+
return sandboxBrokerSeatOf(plane, brokerImage, await runIdentitySourceOf(runId, ctx.runRows?.(), logger));
|
|
303
|
+
},
|
|
304
|
+
});
|
|
249
305
|
if (k8sCfg.cache !== undefined || k8sCfg.s3Snapshot !== undefined)
|
|
250
306
|
spaceReclaimer = createSpaceReclaimer(k8sCfg);
|
|
307
|
+
sandboxSecretSeatGate = () => ensureSandboxSecretSeat(k8sCfg, logger, undefined, () => readSandboxSecretSeat(k8sCfg, "env"));
|
|
308
|
+
readSandboxGitPlane = async () => {
|
|
309
|
+
const premises = sandboxGitPlanePremisesOf(config, { ...((r) => (r !== undefined ? { patchRefusal: r } : {}))(podSpecPatchBrokerRefusal(k8sCfg.podSpecPatch)) });
|
|
310
|
+
const secretSeat = sandboxGitPlaneAsksSecretSeat(premises) ? await readSandboxSecretSeat(k8sCfg, "lease") : undefined;
|
|
311
|
+
return (planeCell.current = judgeSandboxGitPlane({ ...premises, secretSeat }));
|
|
312
|
+
};
|
|
313
|
+
sandboxPodReaper = createSandboxPodReaper({ api: createSandboxPodApi(k8sCfg), logger, metrics });
|
|
251
314
|
void checkSandboxEgressPolicy(k8sCfg)
|
|
252
315
|
.then((gaps) => sayEgressPolicyReading(gaps, logger, k8sCfg.namespace ?? K8S_SANDBOX_NAMESPACE_DEFAULT))
|
|
253
316
|
.catch((e) => logger.error("sandbox_egress_policy_check_crashed", { error: e instanceof Error ? e.message : String(e), effect: "the sandbox egress self-check did not complete this boot — the lane runs; the egress policy was not read" }));
|
|
@@ -446,7 +509,7 @@ export function createExecutionEnv(ctx) {
|
|
|
446
509
|
perTaskImage, sessionEnvSelection, perSessionCwd, setSessionCwd, setSessionShellEnv, setSessionInheritEnv,
|
|
447
510
|
fenceSessionOwner: sessionScoped.fenceSessionOwner,
|
|
448
511
|
dropSessionScoped: sessionScoped.dropSession,
|
|
449
|
-
executionEnvFactory, worktreeReap, sendUserFileTaskEnvs, lspManager, spaceReclaimer,
|
|
512
|
+
executionEnvFactory, worktreeReap, sendUserFileTaskEnvs, lspManager, spaceReclaimer, sandboxSecretSeatGate, sandboxPodReaper, readSandboxGitPlane,
|
|
450
513
|
};
|
|
451
514
|
}
|
|
452
515
|
//# sourceMappingURL=execution-env.js.map
|
|
@@ -41,13 +41,13 @@
|
|
|
41
41
|
*
|
|
42
42
|
* ## 件D 的边界(成文,别读成「数据会被删」)
|
|
43
43
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* (`assertRetentionCapability` ——
|
|
48
|
-
*
|
|
44
|
+
* 三只被托管的 SQL 店(session / checkpoint / tool-result)的 `retention` 声明读一个事实 —— 留存扫车道开不开(`plugins/retention-store-sql.ts` 的
|
|
45
|
+
* `retentionSweepRuns`):开 ⇒ `managed`,关(缺省)⇒ `none`;local 形的店恒声明 `none`。删除的执行面是扫车道(`boot/retention-lane.ts`)与 SQL 店上的
|
|
46
|
+
* 执行器,不在本装配点。所以本装配点对件D 只做两件事:①把策略与执行器递给 core 的启动期校验
|
|
47
|
+
* (`assertRetentionCapability` —— 配对由引擎一个判官判:店声明 `managed` 而部署不跑执行器、执行器不是执行器,锁不锁都拒;锁着 + 店不能删 ⇒ 拒启,
|
|
48
|
+
* 「策略锁着、数据永存」不许发生);②策略在场而没有任何 managed 店时打一条响亮 warn。**不**假装有执行面。
|
|
49
49
|
*/
|
|
50
|
-
import { type LockedKey, type RunnerDeps } from "@sema-agent/core";
|
|
50
|
+
import { type LockedKey, type ManagedRetentionCapability, type RunnerDeps } from "@sema-agent/core";
|
|
51
51
|
import type { ServiceConfig } from "../config.js";
|
|
52
52
|
import type { Logger } from "../observability/logger.js";
|
|
53
53
|
/** 装配产物:三个 core 座席 + 已校验的锁集(同步拒面 `assertRequestMcpUnlocked` 读它)。 */
|
|
@@ -72,18 +72,11 @@ export interface GovernanceSeamsCtx {
|
|
|
72
72
|
store: object | undefined;
|
|
73
73
|
}>;
|
|
74
74
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* 🔴 为什么这一位必须存在(codex 交叉复审 R2-[critical],验真后修):core 的
|
|
79
|
-
* `assertRetentionCapability` 只读**店的声明位**。[ref] 车1 让三只 SQL 店如实声明了 `"managed"`
|
|
80
|
-
* (它们的行确实由托管留存删),于是那道门从此**放行** locked policy —— 可执行器还在车2 手里。
|
|
81
|
-
* 两者之间的窗口如果什么都不做,后果正是本仓最忌的那种:部署自述「策略已受管」、审计与能力面
|
|
82
|
-
* 也这么说,而**没有任何东西在删数据**;车1 之前那条 `retention_policy_not_executed` 的响亮 warn
|
|
83
|
-
* 还会因为"有 managed 店在场"而**静音**。
|
|
84
|
-
* ⇒ 判据改成问「有没有东西真会删」,而不是「有没有店说自己被管」。车2 接上 lane 时把这一位传 true。
|
|
75
|
+
* 交给引擎启动检查的留存执行器 —— 本部署跑扫车道 ⇒ 那只执行器(`backend.retention`),不跑 ⇒ `null`(必填:漏递即编译红,
|
|
76
|
+
* 引擎对 `undefined` 也拒启)。「店说 managed」与「有执行器」的配对由引擎一个判官判(引擎 7.58.0:锁不锁都判);
|
|
77
|
+
* 店的词与这一格读同一个事实(`retention-store-sql.ts` 的 `retentionSweepRuns`),本仓不再另判一遍。
|
|
85
78
|
*/
|
|
86
|
-
|
|
79
|
+
retentionExecutor: ManagedRetentionCapability | null;
|
|
87
80
|
}
|
|
88
81
|
/**
|
|
89
82
|
* 件C 的装配相容性判据(纯,可单测)——见文件头「两条判据」。
|
|
@@ -49,30 +49,18 @@ export function createGovernanceSeams(ctx) {
|
|
|
49
49
|
}
|
|
50
50
|
const retentionPolicy = config.retentionPolicy;
|
|
51
51
|
const locked = lockedKeys.has("retentionPolicy");
|
|
52
|
-
assertRetentionCapability({ policy: retentionPolicy, locked, stores: retentionStores });
|
|
52
|
+
assertRetentionCapability({ policy: retentionPolicy, locked, stores: retentionStores, executor: ctx.retentionExecutor });
|
|
53
53
|
if (retentionPolicy !== undefined) {
|
|
54
54
|
const managed = retentionStores.filter((s) => s.store?.retention === "managed");
|
|
55
|
-
const executorWired = ctx.retentionExecutorWired === true;
|
|
56
55
|
if (managed.length === 0) {
|
|
57
56
|
logger.warn("retention_policy_not_executed", {
|
|
58
57
|
maxAgeDays: retentionPolicy.maxAgeDays,
|
|
59
|
-
note: "RETENTION_MAX_AGE_DAYS is configured but NO wired store declares retention:\"managed\"
|
|
60
|
-
"
|
|
61
|
-
"engine for the startup capability check
|
|
58
|
+
note: "RETENTION_MAX_AGE_DAYS is configured but NO wired store declares retention:\"managed\" (the retention sweep lane is off — " +
|
|
59
|
+
"RETENTION_SWEEP_INTERVAL_SEC unset or 0 — or the store medium has no sweep) — the policy is a DECLARATION only; nothing " +
|
|
60
|
+
"deletes data on its account. It is relayed to the engine for the startup capability check; run the sweep lane on a SQL " +
|
|
61
|
+
"backend to make it effective.",
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
|
-
else if (!executorWired) {
|
|
65
|
-
const detail = `retention policy is configured (maxAgeDays=${retentionPolicy.maxAgeDays}) and ${managed.length} wired store(s) declare ` +
|
|
66
|
-
`retention:"managed", but THIS BUILD WIRES NO RETENTION EXECUTOR (the sweep lane) — nothing enumerates domains or calls ` +
|
|
67
|
-
`the destructive store methods, so no data is deleted on the policy's account. A "managed" declaration is a statement ` +
|
|
68
|
-
`about who OWNS deleting those rows, not proof that a scheduler is running.`;
|
|
69
|
-
if (locked) {
|
|
70
|
-
throw new Error(`${detail} Refusing to start with the retentionPolicy key LOCKED: a locked policy over a deployment that does not ` +
|
|
71
|
-
`actually delete is exactly the "policy locked, data immortal" posture the engine's capability check exists to ` +
|
|
72
|
-
`prevent. Unlock the key, remove the policy, or run a build whose retention sweep lane is wired.`);
|
|
73
|
-
}
|
|
74
|
-
logger.warn("retention_policy_not_executed", { maxAgeDays: retentionPolicy.maxAgeDays, note: detail });
|
|
75
|
-
}
|
|
76
64
|
}
|
|
77
65
|
return { compliancePostureResolver, lockedConfig, retentionPolicy, lockedKeys };
|
|
78
66
|
}
|
package/dist/boot/leader.d.ts
CHANGED
|
@@ -49,6 +49,9 @@ export interface LeaderCtx {
|
|
|
49
49
|
* 唯一出口就是它(`runtask.js` 的 `catch (flushErr) => deps.onError`),所以它与 `usageWindowStore`
|
|
50
50
|
* 席同生共死:挂窗不挂汇 = 治理轴上的静默失败面([ref])。必填键,理由同 `tracer`。 */
|
|
51
51
|
onError: RunnerDeps["onError"];
|
|
52
|
+
/** 部署座 —— 起服第 5 段装配口 `assembleDeploymentMods` 交回的**同一份**(主车道各 Runner 经共享基座吃的就是它)。leader 车道的每一只 Runner 都要带:
|
|
53
|
+
* 缺席 = 运维声明的 mod 包管不到 leader 派出的腿。必填键,理由同 `tracer`。 */
|
|
54
|
+
deploymentMods: NonNullable<RunnerDeps["mods"]>;
|
|
52
55
|
/** [ref] 车4 件1:durable store 后端(leader-run 登记表从这里取)。缺席 = 无 DB 的 env-only worker。 */
|
|
53
56
|
backend?: StoreBackend | undefined;
|
|
54
57
|
}
|
package/dist/boot/leader.js
CHANGED
|
@@ -59,6 +59,7 @@ export function createLeaderFace(ctx) {
|
|
|
59
59
|
: {}),
|
|
60
60
|
...(ctx.promptSource ? { promptSource: ctx.promptSource } : {}),
|
|
61
61
|
...(ctx.onError ? { onError: ctx.onError } : {}),
|
|
62
|
+
mods: ctx.deploymentMods,
|
|
62
63
|
fanoutEnabled: config.leaderFanoutEnabled,
|
|
63
64
|
...((process.env.MODEL_ROUTER_ID || process.env.MODEL_CHEAP_ID)
|
|
64
65
|
? { routerModel: (process.env.MODEL_ROUTER_ID || process.env.MODEL_CHEAP_ID) }
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { principalInboxConsumerOf } from "@sema-agent/core";
|
|
2
2
|
import { createOrgDeliveryGate } from "../org-delivery-gate.js";
|
|
3
|
+
function declarationOf(consumer) {
|
|
4
|
+
switch (consumer.kind) {
|
|
5
|
+
case "assistant":
|
|
6
|
+
return { declared: "PRINCIPAL_INBOX_ASSISTANT declares a principal-inbox consumer", undeclare: "unset PRINCIPAL_INBOX_ASSISTANT" };
|
|
7
|
+
case "terminals":
|
|
8
|
+
return { declared: 'RunnerDeps.principalInboxConsumer declares "terminals" (the scope\'s terminal sessions drain the principal inbox)', undeclare: "drop the RunnerDeps.principalInboxConsumer declaration" };
|
|
9
|
+
default: {
|
|
10
|
+
const unknown = consumer;
|
|
11
|
+
throw new Error(`unknown principal-inbox consumer kind: ${JSON.stringify(unknown)}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
3
15
|
export function mountOrgDeliveryGate(input) {
|
|
4
16
|
const consumer = principalInboxConsumerOf(input.runnerDeps);
|
|
5
17
|
if (consumer.kind === "none")
|
|
@@ -11,8 +23,9 @@ export function mountOrgDeliveryGate(input) {
|
|
|
11
23
|
...(directory === undefined ? ["an organization membership directory (a web-admin center, or MEMORY_ORG_DIRECTORY_JSON)"] : []),
|
|
12
24
|
...(backend === undefined ? ["a store backend for the delivery quota (DB_BACKEND=mysql|pg|local)"] : []),
|
|
13
25
|
];
|
|
14
|
-
|
|
15
|
-
|
|
26
|
+
const { declared, undeclare } = declarationOf(consumer);
|
|
27
|
+
throw new Error(`${declared}, so this deployment must mount the organization delivery gate — but it lacks ${missing.join("; ")}. ` +
|
|
28
|
+
`Refusing to boot rather than run with a declared inbox that nothing may legitimately write to; provide the missing pieces or ${undeclare}.`);
|
|
16
29
|
}
|
|
17
30
|
input.logger.info("org_delivery_gate_mounted", { consumer: consumer.kind });
|
|
18
31
|
return createOrgDeliveryGate({ directory, mailbox: mailboxStore, quota: backend.orgDeliveryQuota(), consumer });
|
package/dist/boot/reapers.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ import type { FileHistoryErasureFace } from "../file-history-capture.js";
|
|
|
25
25
|
import type { ApprovalNonceStore, CheckpointStoreFull, CostQuotaStore, ImageBake, RateLimiterStore, ServiceWorkflowJournalStore, StoreBackend, ToolResultStoreFull } from "../plugins/store-backend.js";
|
|
26
26
|
import type { ToolApprovalCoordinator } from "../tool-approval.js";
|
|
27
27
|
import type { ParkCommitWatch } from "../plugins/park-commit-watch.js";
|
|
28
|
+
import { type SandboxPodReaper } from "../plugins/k8s-pod-reaper.js";
|
|
28
29
|
import { type AuditRotationPort } from "../approval-ask-retention.js";
|
|
29
30
|
/** [ref] / [ref]§五(sema-comms `audits/failopen-governance-176.md` §7 "Z 类 1 条"):default consecutive-failure
|
|
30
31
|
* count before a reaper leg's swallowed error gets a `warn` line. The ~15 `.catch(() => undefined)` sites
|
|
@@ -113,6 +114,8 @@ export interface ReapersCtx {
|
|
|
113
114
|
approvalAskAudit: AuditRotationPort | undefined;
|
|
114
115
|
/** 晚绑(server 造出来才有)——见文件头「位置即契约」①。 */
|
|
115
116
|
getRunDenySweep: () => ((now: number) => Promise<void>) | undefined;
|
|
117
|
+
/** k8s 车道的沙箱 Pod reaper(`plugins/k8s-pod-reaper.ts`;第 5 段与 run 工厂同一份 k8s 配置铸)。缺席 = 非 k8s 车道 ⇒ 本腿零调用。 */
|
|
118
|
+
sandboxPodReaper?: SandboxPodReaper;
|
|
116
119
|
}
|
|
117
120
|
/** core 5.48 `reapDurableAgents` 的 `deps.sessions` 面(结构形,只列本仓要填的三格)。 */
|
|
118
121
|
export interface ReapSessionsFacade {
|
package/dist/boot/reapers.js
CHANGED
|
@@ -4,6 +4,7 @@ import { CostQuota } from "../observability/cost-quota.js";
|
|
|
4
4
|
import { isAdoptionQuiescing, trackMaintenanceLeg } from "../adoption/quiesce.js";
|
|
5
5
|
import { createApprovalReconciler } from "../approval-reconciler.js";
|
|
6
6
|
import { createE2bOrphanSandboxProvider, reclaimOrphanE2bSandboxes, E2B_ORPHAN_GRACE_MS } from "../plugins/e2b-orphan-reclaim.js";
|
|
7
|
+
import { SANDBOX_POD_REAP_PERIOD_MS } from "../plugins/k8s-pod-reaper.js";
|
|
7
8
|
import { APPROVAL_ASK_RETENTION_PASS_MS, runApprovalAskRetentionPass } from "../approval-ask-retention.js";
|
|
8
9
|
export const REAPER_FAILURE_WARN_THRESHOLD = 5;
|
|
9
10
|
export function createThrottledReaperCatch(name, logger, threshold = REAPER_FAILURE_WARN_THRESHOLD) {
|
|
@@ -57,7 +58,7 @@ export function createPlacementAwareReapSessions(deps) {
|
|
|
57
58
|
};
|
|
58
59
|
}
|
|
59
60
|
export function startReapers(ctx) {
|
|
60
|
-
const { config, logger, metrics, localRoot, backend, subRunner, runStore, checkpointStore, parkCommits, rateLimiter, costQuota, toolResultStore, fileHistoryErasure, taskAttachmentStore, imageBakes, worktreeReap, workflowNotifyGate, workflowRecoverOpts, workflowJournalStore, sqlWorkflowRunStore, workflowNotifyJournal, rosterStore, backgroundAgentStore, mailboxStore, toolApproval, permissionRuleStores, approvalNonceStore, getRunDenySweep, userInputLedger, approvalAskAudit, } = ctx;
|
|
61
|
+
const { config, logger, metrics, localRoot, backend, subRunner, runStore, checkpointStore, parkCommits, rateLimiter, costQuota, toolResultStore, fileHistoryErasure, taskAttachmentStore, imageBakes, worktreeReap, workflowNotifyGate, workflowRecoverOpts, workflowJournalStore, sqlWorkflowRunStore, workflowNotifyJournal, rosterStore, backgroundAgentStore, mailboxStore, toolApproval, permissionRuleStores, approvalNonceStore, getRunDenySweep, userInputLedger, approvalAskAudit, sandboxPodReaper, } = ctx;
|
|
61
62
|
const leg = (p) => {
|
|
62
63
|
if (p !== undefined)
|
|
63
64
|
trackMaintenanceLeg(p);
|
|
@@ -73,6 +74,8 @@ export function startReapers(ctx) {
|
|
|
73
74
|
: undefined;
|
|
74
75
|
let e2bOrphanLastRunMs = Date.now() - E2B_ORPHAN_GRACE_MS;
|
|
75
76
|
let e2bOrphanInFlight = false;
|
|
77
|
+
let sandboxPodReapLastRunMs = Date.now() - SANDBOX_POD_REAP_PERIOD_MS;
|
|
78
|
+
let sandboxPodReapInFlight = false;
|
|
76
79
|
let wfRunReapInFlight = false;
|
|
77
80
|
let attachmentSweepInFlight = false;
|
|
78
81
|
let bgAgentReapInFlight = false;
|
|
@@ -80,6 +83,7 @@ export function startReapers(ctx) {
|
|
|
80
83
|
const probeClockSkewGuard = createThrottledReaperCatch("probe_clock_skew", logger);
|
|
81
84
|
const runsReapStaleGuard = createThrottledReaperCatch("runs_reap_stale", logger);
|
|
82
85
|
const e2bOrphanGuard = createThrottledReaperCatch("e2b_orphan_reclaim", logger);
|
|
86
|
+
const sandboxPodReapGuard = createThrottledReaperCatch("sandbox_pod_reap", logger);
|
|
83
87
|
const checkpointsReapExpiredGuard = createThrottledReaperCatch("checkpoints_reap_expired", logger);
|
|
84
88
|
const approvalNonceReapExpiredGuard = createThrottledReaperCatch("approval_nonce_reap_expired", logger);
|
|
85
89
|
const runsFailSuspendedExpiredCheckpointGuard = createThrottledReaperCatch("runs_fail_suspended_expired_checkpoint", logger);
|
|
@@ -366,6 +370,16 @@ export function startReapers(ctx) {
|
|
|
366
370
|
e2bOrphanInFlight = false;
|
|
367
371
|
}));
|
|
368
372
|
}
|
|
373
|
+
if (sandboxPodReaper && Date.now() - sandboxPodReapLastRunMs >= SANDBOX_POD_REAP_PERIOD_MS && !sandboxPodReapInFlight) {
|
|
374
|
+
sandboxPodReapInFlight = true;
|
|
375
|
+
sandboxPodReapLastRunMs = Date.now();
|
|
376
|
+
leg(sandboxPodReaper
|
|
377
|
+
.reapOnce(runStore)
|
|
378
|
+
.then(() => sandboxPodReapGuard.onSuccess(), sandboxPodReapGuard.onError)
|
|
379
|
+
.finally(() => {
|
|
380
|
+
sandboxPodReapInFlight = false;
|
|
381
|
+
}));
|
|
382
|
+
}
|
|
369
383
|
}, config.reapIntervalSec * 1000);
|
|
370
384
|
reaper.unref?.();
|
|
371
385
|
return reaper;
|
|
@@ -2,6 +2,7 @@ import { type MemoryBackend } from "@sema-agent/core";
|
|
|
2
2
|
import { SessionEnvironmentSelection, selectEnvironmentTool } from "../capabilities/select-environment-tool.js";
|
|
3
3
|
import { sendUserFileTool } from "../capabilities/send-user-file-tool.js";
|
|
4
4
|
import { selectScenario } from "../capabilities/scenarios.js";
|
|
5
|
+
import { type LoadedSkill } from "../capabilities/skills.js";
|
|
5
6
|
import type { ServiceConfig } from "../config.js";
|
|
6
7
|
import { type LiveQuestionFace } from "../deployment-governance.js";
|
|
7
8
|
import { FleetEventBus } from "../fleet/fleet-bus.js";
|
|
@@ -17,6 +18,7 @@ import { type TaskAttachmentStore } from "../plugins/task-attachment-store.js";
|
|
|
17
18
|
import { type createPrincipalEntitlementsClient } from "../runtime-caps-resolver.js";
|
|
18
19
|
import { type OwnerAwareSessionStore } from "../security.js";
|
|
19
20
|
import type { MemorySyncRunner } from "../memory-sync-client.js";
|
|
21
|
+
import type { PeerDesk } from "../peer-seat.js";
|
|
20
22
|
import type { RunnerDepsOnAsk } from "./runner-deps.js";
|
|
21
23
|
type PrincipalCaps = ReturnType<typeof createPrincipalEntitlementsClient>;
|
|
22
24
|
/** `resolveSpec` 原先从 `main()` 闭包里拿到的全部 boot 局部量。 */
|
|
@@ -83,6 +85,11 @@ export interface ResolveSpecCtx {
|
|
|
83
85
|
/** [ref] 件C:本部署已校验的锁集(boot/governance-seams.ts 的产物,与 `RunnerDeps.lockedConfig`
|
|
84
86
|
* 同源一次解析)。空集 = 无锁 = 现行为。本域只用它做**同步拒面**(§4.3),不做第二次裁决。 */
|
|
85
87
|
lockedKeys: ReadonlySet<import("@sema-agent/core").LockedKey>;
|
|
88
|
+
/** 本进程的对端座 desk(stage-05 建、HTTP 服务的 `peerDesk` 同一只):请求面 MCP / A2A 的胜出草稿在 `opts.lease` 下经它登记,换回声明带的引用 —— 两只漏斗开的租约属于它。 */
|
|
89
|
+
peerDesk: PeerDesk;
|
|
90
|
+
/** 本部署**装载簿**(stage-07 的出厂技能 + 配置源覆盖之后的终表,场景工厂读的同一份)。本装配器只拿它答「场景交来的这只技能来自哪里」
|
|
91
|
+
* (run 名册 `wiring_manifest.skills[].source`,`buildRunSkills`);名字在装载簿里唯一(装载器同名即抛、配置源按名覆盖)。 */
|
|
92
|
+
loadedSkills: readonly LoadedSkill[];
|
|
86
93
|
}
|
|
87
94
|
export declare function createResolveSpec(ctx: ResolveSpecCtx): ServiceDeps["resolveSpec"];
|
|
88
95
|
export {};
|