@sema-agent/server 7.125.1 → 7.126.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 +195 -2
- package/README.md +2 -2
- package/README.zh-CN.md +2 -2
- package/USAGE.md +263 -140
- package/deploy/sema-up/README.md +1 -1
- package/deploy/sema-up/chart/templates/networkpolicy-sandbox.yaml +47 -0
- package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +5 -1
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +2 -2
- package/deploy/sema-up/chart/templates/server.yaml +1 -1
- package/deploy/sema-up/chart/values.yaml +12 -0
- package/deploy/sema-up/cluster-up.sh +10 -10
- package/deploy/sema-up/kube-up.sh +11 -10
- package/deploy/sema-up/lib/dataroot.sh +1 -1
- package/deploy/sema-up/lib/envf.sh +5 -5
- package/deploy/sema-up/lib/flagshape.sh +5 -5
- package/deploy/sema-up/lib/lanes.py +1 -1
- package/deploy/sema-up/lib/parse-machines.py +2 -2
- package/deploy/sema-up/lib/shell-access.sh +1 -1
- package/deploy/sema-up/preflight.sh +4 -4
- package/deploy/sema-up/sema-up.sh +33 -33
- package/deploy/sema-up/smoke.sh +3 -3
- package/deploy/sema-up/stack/compose.yaml +1 -1
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +6 -2
- package/dist/approval-card.d.ts +20 -4
- package/dist/approval-content-kind.d.ts +38 -22
- package/dist/approval-content-kind.js +20 -4
- package/dist/audit.js +2 -0
- package/dist/bench/s1/arms.d.ts +9 -37
- package/dist/bench/s1/arms.js +4 -61
- package/dist/bench/s1/live-deps.d.ts +4 -10
- package/dist/bench/s1/live-deps.js +1 -222
- package/dist/bench/s1/oracle.d.ts +1 -1
- package/dist/bench/s1/reviewer.d.ts +1 -1
- package/dist/bench/s1/row.d.ts +5 -7
- package/dist/bench/s1/row.js +0 -2
- package/dist/bench/s1/run-firm.d.ts +2 -2
- package/dist/bench/s1/run-firm.js +1 -4
- package/dist/bench/s1/runner-ctx.d.ts +17 -29
- package/dist/bench/s1/runner-ctx.js +3 -7
- package/dist/bench/s1/tasks.d.ts +9 -46
- package/dist/bench/s1/tasks.js +4 -63
- package/dist/boot/execution-env.d.ts +38 -26
- package/dist/boot/execution-env.js +71 -38
- package/dist/boot/memory-boundary.d.ts +1 -1
- package/dist/boot/parked-revive-gate.d.ts +0 -3
- package/dist/boot/parked-revive-gate.js +2 -2
- package/dist/boot/resolve-spec.d.ts +0 -2
- package/dist/boot/resolve-spec.js +12 -17
- package/dist/boot/retention-lane.d.ts +12 -1
- package/dist/boot/retention-lane.js +2 -0
- package/dist/boot/runner-deps.d.ts +5 -5
- package/dist/boot/runner-deps.js +5 -16
- package/dist/boot/session-faces.d.ts +5 -1
- package/dist/boot/session-faces.js +37 -1
- package/dist/boot/stage-03-store-backend.d.ts +1 -0
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -0
- package/dist/boot/stage-05-execution-env.d.ts +2 -2
- package/dist/boot/stage-05-execution-env.js +7 -4
- package/dist/boot/stage-06-runners.d.ts +2 -3
- package/dist/boot/stage-06-runners.js +8 -7
- package/dist/boot/stage-07-capability-layer.d.ts +2 -3
- package/dist/boot/stage-07-capability-layer.js +3 -4
- package/dist/boot/stage-08-reapers.d.ts +2 -3
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +2 -3
- package/dist/boot/stage-09-leader.js +2 -1
- package/dist/boot/stage-10-http-server.d.ts +2 -3
- package/dist/boot/stage-10-http-server.js +2 -2
- package/dist/boot/stores.d.ts +1 -0
- package/dist/boot/stores.js +4 -3
- package/dist/boot/web-admin.d.ts +5 -0
- package/dist/boot/web-admin.js +28 -14
- package/dist/brain.d.ts +2 -2
- package/dist/brain.js +1 -1
- package/dist/capabilities/builtin-tools.d.ts +2 -1
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/hands-lane.d.ts +9 -6
- package/dist/capabilities/hands-lane.js +2 -2
- package/dist/capabilities/memory-notice.d.ts +27 -22
- package/dist/capabilities/memory-notice.js +15 -17
- package/dist/capabilities/scenarios.d.ts +9 -14
- package/dist/capabilities/scenarios.js +5 -50
- package/dist/capability-facts.d.ts +22 -11
- package/dist/capability-facts.js +13 -6
- package/dist/config-catalog.js +11 -4
- package/dist/config-provider.d.ts +5 -1
- package/dist/config-provider.js +23 -4
- package/dist/config-types.d.ts +14 -1
- package/dist/config.js +39 -6
- package/dist/deployment-governance.d.ts +19 -21
- package/dist/deployment-governance.js +7 -8
- package/dist/env-name-allowlist-knobs.d.ts +5 -5
- package/dist/env-name-allowlist-knobs.js +1 -0
- package/dist/execution-lane-caps.js +2 -2
- package/dist/hooks/hook-runner.d.ts +84 -30
- package/dist/hooks/hook-runner.js +74 -41
- package/dist/http/admission.js +12 -9
- package/dist/http/durable-run-leg.d.ts +5 -4
- package/dist/http/durable-run-leg.js +1 -1
- package/dist/http/idempotency.d.ts +28 -6
- package/dist/http/idempotency.js +10 -2
- package/dist/http/principal-gate.d.ts +14 -0
- package/dist/http/principal-gate.js +7 -0
- package/dist/http/request-guards.d.ts +2 -1
- package/dist/http/request-guards.js +14 -14
- package/dist/http/resume-legs.d.ts +2 -2
- package/dist/http/resume-legs.js +5 -4
- package/dist/http/route-ctx.d.ts +8 -6
- package/dist/http/routes/a2a-serve.js +11 -7
- package/dist/http/routes/approvals-assistant.js +18 -3
- package/dist/http/routes/background.d.ts +1 -1
- package/dist/http/routes/background.js +1 -1
- package/dist/http/routes/capabilities.js +10 -2
- package/dist/http/routes/mcp-reconnect.js +1 -1
- package/dist/http/routes/runs.d.ts +4 -3
- package/dist/http/routes/runs.js +12 -13
- package/dist/http/routes/session-sync.js +14 -11
- package/dist/http/routes/sessions.js +9 -9
- package/dist/http/routes/side-query.js +6 -19
- package/dist/http/routes/tasks.js +12 -11
- package/dist/http/server.d.ts +4 -0
- package/dist/http/server.js +2 -2
- package/dist/http/submit-replay.d.ts +15 -8
- package/dist/http/submit-replay.js +6 -0
- package/dist/http/wire-types.d.ts +7 -9
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/internal-run-env.d.ts +30 -0
- package/dist/internal-run-env.js +11 -0
- package/dist/leader/wire.js +3 -2
- package/dist/memory-scope.d.ts +19 -7
- package/dist/memory-scope.js +25 -8
- package/dist/observability/fail-open.d.ts +15 -3
- package/dist/observability/fail-open.js +15 -3
- package/dist/observability/metrics.d.ts +0 -1
- package/dist/observability/metrics.js +0 -3
- package/dist/observability/run-terminal.js +69 -4
- package/dist/permission-rule-vocab.d.ts +3 -2
- package/dist/permission-rule-vocab.js +1 -1
- package/dist/plan-cache-probe.d.ts +3 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
- package/dist/plugins/caching-session-store.d.ts +3 -0
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-store-sql.d.ts +42 -28
- package/dist/plugins/checkpoint-store-sql.js +57 -11
- package/dist/plugins/file-run-store.d.ts +25 -21
- package/dist/plugins/file-run-store.js +70 -34
- package/dist/plugins/local-checkpoint-store.d.ts +8 -5
- package/dist/plugins/local-checkpoint-store.js +5 -15
- package/dist/plugins/local-session-store.d.ts +66 -7
- package/dist/plugins/local-session-store.js +168 -101
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +1 -1
- package/dist/plugins/memory-run-store.d.ts +19 -3
- package/dist/plugins/memory-run-store.js +38 -3
- package/dist/plugins/one-time-migrations.d.ts +141 -39
- package/dist/plugins/one-time-migrations.js +32 -143
- package/dist/plugins/pg-pool.js +11 -1
- package/dist/plugins/pg-session-storage.d.ts +2 -0
- package/dist/plugins/pg-session-storage.js +9 -5
- package/dist/plugins/remote-env-adb.d.ts +3 -0
- package/dist/plugins/remote-env-adb.js +1 -0
- package/dist/plugins/remote-env-device.d.ts +3 -0
- package/dist/plugins/remote-env-device.js +1 -0
- package/dist/plugins/remote-env-e2b.d.ts +4 -0
- package/dist/plugins/remote-env-e2b.js +2 -1
- package/dist/plugins/remote-env-host.d.ts +12 -0
- package/dist/plugins/remote-env-host.js +11 -1
- package/dist/plugins/remote-env-k8s.d.ts +227 -39
- package/dist/plugins/remote-env-k8s.js +450 -75
- package/dist/plugins/remote-env-local-docker.d.ts +4 -0
- package/dist/plugins/remote-env-local-docker.js +2 -1
- package/dist/plugins/remote-env-ssh.d.ts +3 -0
- package/dist/plugins/remote-env-ssh.js +1 -0
- package/dist/plugins/retention-store-sql.d.ts +4 -1
- package/dist/plugins/retention-store-sql.js +11 -9
- package/dist/plugins/run-store-sql.d.ts +44 -6
- package/dist/plugins/run-store-sql.js +92 -27
- package/dist/plugins/session-capture-record-store-sql.d.ts +2 -3
- package/dist/plugins/sql-driver.d.ts +2 -1
- package/dist/plugins/store-backend.js +1 -1
- package/dist/plugins/store-contracts.d.ts +17 -3
- package/dist/plugins/tidb-pool.js +15 -3
- package/dist/plugins/tidb-session-storage.js +3 -2
- package/dist/plugins/tidb-session-store.d.ts +2 -0
- package/dist/plugins/tidb-session-store.js +6 -2
- package/dist/request-key-closure.d.ts +12 -0
- package/dist/request-key-closure.js +3 -3
- package/dist/router/route-orchestration.d.ts +3 -11
- package/dist/router/route-orchestration.js +0 -4
- package/dist/rule-entry-list.js +0 -4
- package/dist/rules-consent.js +3 -0
- package/dist/run-local.d.ts +5 -4
- package/dist/run-local.js +23 -17
- package/dist/runs.js +1 -0
- package/dist/security.d.ts +7 -0
- package/dist/security.js +5 -0
- package/dist/server-secret-env.d.ts +10 -4
- package/dist/server-secret-env.js +4 -1
- package/dist/session-incarnation.d.ts +46 -2
- package/dist/session-incarnation.js +14 -3
- package/dist/session-sync-kernel.d.ts +10 -3
- package/dist/spec-fields.d.ts +24 -8
- package/dist/spec-fields.js +21 -2
- package/dist/task-workflow.d.ts +6 -4
- package/dist/task-workflow.js +3 -2
- package/dist/tool-approval.d.ts +78 -6
- package/dist/tool-approval.js +7 -3
- package/dist/trace/core-keyset-guard.d.ts +4 -4
- package/dist/trace/engine-notice-wire.d.ts +26 -1
- package/dist/trace/engine-notice-wire.js +7 -2
- package/dist/trace/project.d.ts +8 -3
- package/dist/trace/project.js +15 -1
- package/dist/trace/self-minted-wire.d.ts +104 -2
- package/dist/trace/self-minted-wire.js +35 -0
- package/dist/web-admin-client/apply-effective.d.ts +13 -7
- package/dist/web-admin-client/apply-effective.js +11 -26
- package/dist/web-admin-client/apply-ledger.d.ts +2 -2
- package/dist/web-admin-client/candidate-gate.d.ts +39 -4
- package/dist/web-admin-client/candidate-gate.js +9 -2
- package/dist/web-admin-client/facade.d.ts +2 -2
- package/dist/web-admin-client/http-client.d.ts +3 -1
- package/dist/web-admin-client/http-client.js +4 -3
- package/dist/web-admin-client/read-warnings.d.ts +33 -5
- package/dist/web-admin-client/read-warnings.js +41 -6
- package/dist/web-admin-client/types.d.ts +11 -5
- package/dist/workspace-cache.d.ts +45 -0
- package/dist/workspace-cache.js +30 -0
- package/dist/workspace-space-commit.d.ts +116 -0
- package/dist/workspace-space-commit.js +117 -0
- package/dist/workspace-space.d.ts +75 -9
- package/dist/workspace-space.js +52 -1
- package/package.json +4 -4
- package/dist/boot/session-incarnation-seat.d.ts +0 -41
- package/dist/boot/session-incarnation-seat.js +0 -69
- package/dist/capabilities/code-review-council.d.ts +0 -49
- package/dist/capabilities/code-review-council.js +0 -111
- package/dist/capabilities/collab-wire.d.ts +0 -36
- package/dist/capabilities/collab-wire.js +0 -2
- package/dist/capabilities/collab-workflows.d.ts +0 -47
- package/dist/capabilities/collab-workflows.js +0 -90
- package/dist/capabilities/prompts/code-review.d.ts +0 -25
- package/dist/capabilities/prompts/code-review.js +0 -39
- package/dist/capabilities/prompts/team.d.ts +0 -10
- package/dist/capabilities/prompts/team.js +0 -6
- package/dist/capabilities/team.d.ts +0 -113
- package/dist/capabilities/team.js +0 -70
package/dist/config-catalog.js
CHANGED
|
@@ -2,7 +2,8 @@ import { CROSS_SESSION_INBOUND_SETTINGS, CROSS_SESSION_DIALOG_EXPIRY_VALUES } fr
|
|
|
2
2
|
import { GLOBAL_SCOPE } from "@sema-agent/settings-schema/api/scopes";
|
|
3
3
|
import { WEB_ADMIN_ENV, DOMAIN_SCHEMAS, buildRetiredEnvWire } from "@sema-agent/settings-schema";
|
|
4
4
|
import { CENTER_CREDENTIAL_RENEW_LEAD_DEFAULT_MS, CENTER_CREDENTIAL_RENEW_LEAD_MAX_MS, CENTER_CREDENTIAL_RENEW_LEAD_MIN_MS } from "./center-credential-renewer.js";
|
|
5
|
-
import {
|
|
5
|
+
import { WORKSPACE_CACHE_DEFAULT, WORKSPACE_CACHE_MOUNT_DEFAULT, WORKSPACE_CACHE_SIZE_DEFAULT, WORKSPACE_CACHE_WORDS } from "./workspace-cache.js";
|
|
6
|
+
import { WORKSPACE_PERSIST_DEFAULT, WORKSPACE_PERSIST_WORDS, WORKSPACE_SNAPSHOT_KEEP_DEFAULT, WORKSPACE_SNAPSHOT_KEEP_RANGE, WORKSPACE_SNAPSHOT_TIMEOUT_MS_DEFAULT, WORKSPACE_SNAPSHOT_TIMEOUT_MS_RANGE } from "./workspace-space.js";
|
|
6
7
|
import { THINKING_FORMATS } from "./model-compat.js";
|
|
7
8
|
import { AUTO_MODE_CLASSIFIER_TIMEOUT_BOUNDS, CENTER_BASE_URL_RULE, CONFIG_PROVIDER_WORDS, DRAIN_SECOND_SIGNAL_MIN_GAP_BOUNDS, DRAIN_SECOND_SIGNAL_MIN_GAP_DEFAULT_MS, FIRST_BYTE_TIMEOUT_BOUNDS, FLEET_LEASE_OUTAGE_MAX_DEFAULT_MS, RESILIENCE_DEFAULTS, TASK_WRITE_FACE_ESCALATIONS } from "./config-types.js";
|
|
8
9
|
import { webSearchProviderFromEnv, WEB_SEARCH_PROVIDERS } from "./plugins/web-search.js";
|
|
@@ -65,7 +66,7 @@ export const CONFIG_CATALOG = [
|
|
|
65
66
|
r("APPROVAL_HMAC_KEYS", "approval", "secret", "直连门(D-G)HMAC 完整性密钥集(空=直连门不激活)", { danger: SEC }),
|
|
66
67
|
r("APPROVAL_NEVER_AUTO", "approval", "csv", "永不被 AUTO_BUDGET 自动放行的工具集(不可逆动作恒要人)", { danger: SEC, configKey: "approvalNeverAuto" }),
|
|
67
68
|
r("APPROVAL_REQUIRE", "approval", "csv", "必须人审的工具名单(F4 门;center 腿热:refresh 拍整表换代,无 checkpoint 店的部署发非空名单 ⇒ 审批组整组拒)", { danger: SEC, configKey: "approvalRequire", center: cGov("approvalRequire") }),
|
|
68
|
-
r("APPROVAL_TERMINAL_BACKSTOP_MS", "approval", "number", "
|
|
69
|
+
r("APPROVAL_TERMINAL_BACKSTOP_MS", "approval", "number", "checkpoint 店(SQL 与 local 文件孪生同一公式)pending 行的 crash-safe 绝对 GC 上限(ms;下限 60s,非有限值落默认)", { staticDefault: String(30 * 86_400_000), danger: DATA }),
|
|
69
70
|
r("APPROVAL_TIMEOUT_SEC", "approval", "number", "durable HITL 等人上限(秒);0=无限期等,时间型 suspended 回收不跑", { staticDefault: "0", configKey: "approvalTimeoutSec" }),
|
|
70
71
|
r("ASK_QUESTION_ENABLED", "approval", "boolean", "AskUserQuestion 活流 HITL 装配开关", { derivedDefaultNote: "posture 三态:显式词恒赢,缺席 = 单用户(REQUIRE_PRINCIPAL≠true)⇒ on / 多租户 ⇒ off", configKey: "askQuestionEnabled" }),
|
|
71
72
|
r("ATTACHMENT_MAX_BYTES", "limitsHttp", "number", "附件单文件字节上限(上传整段内存缓冲的 RAM 束)", { staticDefault: String(32 * 1024 * 1024), configKey: "attachmentMaxBytes", center: cLimits("attachmentMaxBytes") }),
|
|
@@ -193,6 +194,7 @@ export const CONFIG_CATALOG = [
|
|
|
193
194
|
r("K8S_MOUNT_PATH", "orchestration", "path", "k8s 工作区挂载路径"),
|
|
194
195
|
r("K8S_NAMESPACE", "orchestration", "string", "沙箱 pod namespace"),
|
|
195
196
|
r("K8S_RUNTIME_CLASS", "orchestration", "string", "沙箱 pod runtimeClass(Kata 等)"),
|
|
197
|
+
r("K8S_SANDBOX_ENV", "orchestration", "secret", "转发进 k8s 沙箱 pod 容器 env 的本进程 env 点名表(NAME,NAME;点到的键从 worker env 原样取,值只进 pod env —— 不进 spec 的其它位置 / 工作区 / 快照 / center / 事件日志;与 LSP_ENV_ALLOW / E2B_SANDBOX_ENV / DOCKER_SANDBOX_ENV 同一只解析器与「点名放行」谓词:形错 / 点名名单型旋钮拒启且不回显值;本进程环境里没有的名按序号 warn、不转发;与包源派生 env 撞名时显式名单胜;只在本车道被选中时求值;原文按凭据类对待:只回在场位、不进任何子进程)", { danger: SEC }),
|
|
196
198
|
r("K8S_SANDBOX_IMAGE", "orchestration", "string", "k8s 车道沙箱镜像(REMOTE_EXEC=k8s 必需件)"),
|
|
197
199
|
r("K8S_TIMEOUT_MS", "orchestration", "number", "k8s 沙箱 pod 寿命(activeDeadlineSeconds,ms;整只 pod 的泄漏护栏,后台任务超时也被它钳;各条命令的超时见工具超时)"),
|
|
198
200
|
r("K8S_TOKEN", "orchestration", "secret", "k8s API token(缺席走 in-cluster SA)", { danger: SEC }),
|
|
@@ -454,7 +456,7 @@ export const CONFIG_CATALOG = [
|
|
|
454
456
|
r("TASK_MAX_OUTPUT_TOKENS_MAX", "limitsHttp", "number", "调用方自报 limits.maxOutputTokens 的运营方封顶(Math.min 钳显式请求值;坏值=封顶不生效+响亮 warn)", { danger: BILL, derivedDefaultNote: "缺席 ⇒ 不封顶" }),
|
|
455
457
|
r("TASK_MAX_TURNS_MAX", "limitsHttp", "number", "调用方自报 limits.maxTurns 的运营方封顶(同族三旋钮;只钳显式请求值,不是全队默认限额)", { danger: BILL, derivedDefaultNote: "缺席 ⇒ 不封顶" }),
|
|
456
458
|
r("TASK_TIMEOUT_MAX_SEC", "limitsHttp", "number", "调用方自报 limits.timeoutSec 的运营方封顶(同族三旋钮)", { danger: BILL, derivedDefaultNote: "缺席 ⇒ 不封顶" }),
|
|
457
|
-
r("TASK_TIMEOUT_SEC", "limitsHttp", "number", "任务墙钟超时(秒);0/缺席=按 tenancy(单用户无墙;多租户 2400s
|
|
459
|
+
r("TASK_TIMEOUT_SEC", "limitsHttp", "number", "任务墙钟超时(秒);0/缺席=按 tenancy(单用户无墙;多租户 2400s);正值**只抬不降**(Math.max 基值);负值拒启", { staticDefault: "0", derivedDefaultNote: "0/缺席 ⇒ 单用户无墙、多租户 2400s;要低于基值的配速请用 body.limits.maxWalltimeMs" }),
|
|
458
460
|
r("TASK_WRITE_FACE_ESCALATION", "orchestration", "enum", "任务层「掀开写围栏」声明的运维天花板档位(S-591;只抬天花板,不是部署席)", { enumValues: [...TASK_WRITE_FACE_ESCALATIONS], danger: SEC, derivedDefaultNote: "三态:allow ⇒ 任务层 bypassPermissions 的开放写面成立;refuse ⇒ 无条件拒;**缺席 = 本层不表态** ⇒ 按托管 posture 判(托管拒 / 单用户 turnkey 放行)。判据单点 src/hosted-posture.ts;device 车道不适用(成文裁定:那条穿越结构性不存在)", configKey: "taskWriteFaceEscalation" }),
|
|
459
461
|
r("TOOL_APPROVAL_ENABLED", "approval", "boolean", "活体工具审批 HITL(onAsk 装配;关 ⇒ core resolveAsk 走 headless 缺省)", { danger: SEC, derivedDefaultNote: "posture 三态:显式词恒赢,缺席 = 单用户(REQUIRE_PRINCIPAL≠true)⇒ on / 多租户 ⇒ off", configKey: "toolApprovalEnabled" }),
|
|
460
462
|
r("TOOL_DEFER_LONGTAIL", "orchestration", "boolean", "长尾一方工具 defer 呈现(实验)", { staticDefault: "false", configKey: "toolDeferLongtail" }),
|
|
@@ -479,11 +481,16 @@ export const CONFIG_CATALOG = [
|
|
|
479
481
|
r("WORKFLOW_RUN_STORE", "orchestration", "enum", "后台 workflow run 店后端(auto=有 SQL 用 SQL,否则 File)", { enumValues: ["auto", "file", "memory"], staticDefault: "auto", configKey: "workflowRunStoreBackend" }),
|
|
480
482
|
r("WORKFLOW_SIZE_GUIDELINE", "orchestration", "enum", "Workflow 工具卡的规模建议(advisory;typo 拒启)", { enumValues: ["small", "medium", "large", "unrestricted"], configKey: "workflowSizeGuideline" }),
|
|
481
483
|
r("WORKFLOW_TOTAL_TIMEOUT_MS", "orchestration", "number", "workflow 脚本总时限(ms;0/负不是禁用 —— 无禁用臂)", { staticDefault: "3600000" }),
|
|
484
|
+
r("WORKSPACE_CACHE", "orchestration", "enum", "k8s 按工作区空间的构建缓存卷:volume = 每个空间(会话住客)一只 PVC(ws-cache-<摘要>,标签 sema.space,StorageClass 用集群缺省),挂到 WORKSPACE_CACHE_MOUNT,并在 pod env 注入工具缓存闭表(GRADLE_USER_HOME / MAVEN_OPTS / npm_config_cache / PIP_CACHE_DIR / UV_CACHE_DIR / GOMODCACHE;Rust 依赖缓存不盖 —— Cargo 没有只放下载缓存的 env;K8S_SANDBOX_ENV 同名显式值胜);卷在快照之外、可丢,pod 删卷留;卷拿不到(建不成 / 快照时限内没绑定)⇒ run 照起、无卷无缓存 env,fail-open 计数 + 一行 workspace_cache_unavailable;off = 不建卷。前提:会话店读得出会话住客(内存会话店 × volume ⇒ 拒启);委派子代不挂卷;词表外拒启", { enumValues: WORKSPACE_CACHE_WORDS, staticDefault: WORKSPACE_CACHE_DEFAULT }),
|
|
485
|
+
r("WORKSPACE_CACHE_MOUNT", "orchestration", "path", "k8s 构建缓存卷在沙箱 pod 里的挂载点(绝对路径;与工作区挂载 K8S_MOUNT_PATH 相同 / 互相嵌套 ⇒ 拒启;只在 WORKSPACE_CACHE=volume 时读)", { staticDefault: WORKSPACE_CACHE_MOUNT_DEFAULT }),
|
|
486
|
+
r("WORKSPACE_CACHE_SIZE", "orchestration", "string", "k8s 构建缓存卷的大小(PVC 申请量,k8s quantity 形如 20Gi / 500Mi;形不合拒启;只在 WORKSPACE_CACHE=volume 时读)", { staticDefault: WORKSPACE_CACHE_SIZE_DEFAULT }),
|
|
482
487
|
r("WORKSPACE_FILE_MAX_BYTES", "limitsHttp", "number", "已随 workspace 浏览面退役(S-15):值照常校验/落值,应用于空(重启也不生效)", { envTiming: "inert", configKey: "workspaceFileMaxBytes", center: cLimits("workspaceFileMaxBytes", { timing: "inert" }) }),
|
|
483
|
-
r("WORKSPACE_PERSIST", "orchestration", "enum", "k8s
|
|
488
|
+
r("WORKSPACE_PERSIST", "orchestration", "enum", "k8s 工作区跨轮保留:space(缺省)= 每条 run 结束把 /workspace 快照进本会话住客的空间、下一条 run 开始恢复最近一份(上一条还在保存 ⇒ 下一条等它存完,最多等一个上传时限,见 USAGE §9.3b);off = 每轮新建。space(含缺省)却没配快照存储(MINIO_* 三键)⇒ 不生效,起服一行 workspace_persist_unavailable 点名缺键;前提:会话店读得出会话住客(local / SQL 会话店),内存会话店 × space(含缺省,且配了快照存储)⇒ 拒启(出路 WORKSPACE_PERSIST=off);词表外拒启", { enumValues: WORKSPACE_PERSIST_WORDS, staticDefault: WORKSPACE_PERSIST_DEFAULT, danger: DATA }),
|
|
484
489
|
r("WORKSPACE_SNAPSHOT_BUCKET", "orchestration", "string", "k8s 工作区快照桶", { derivedDefaultNote: "缺席 ⇒ workspaces" }),
|
|
490
|
+
r("WORKSPACE_SNAPSHOT_EXCLUDE", "orchestration", "csv", "k8s 工作区快照的排除表(相对工作区根的 tar 排除模式,逗号分隔,如 build,.gradle,node_modules/.cache;每项一个 --exclude=./<项>,run 末快照与停驻挂起同一张表 —— 排除的目录恢复后不在,构建产物本就可再生;项形闭:相对路径段,不含 .. / 前导 / / 空白 / 引号,坏项拒启并点名第几项;不读项目 .gitignore)", { derivedDefaultNote: "缺席 = 不排除(上传命令与旧版逐字同)" }),
|
|
485
491
|
r("WORKSPACE_SNAPSHOT_KEEP", "orchestration", "number", `k8s 工作区每个空间(会话住客)保留的快照份数(整数 [${WORKSPACE_SNAPSHOT_KEEP_RANGE.min}, ${WORKSPACE_SNAPSHOT_KEEP_RANGE.max}];写新快照后删最老的;域外拒启)`, { staticDefault: String(WORKSPACE_SNAPSHOT_KEEP_DEFAULT), danger: DATA }),
|
|
486
492
|
r("WORKSPACE_SNAPSHOT_PREFIX", "orchestration", "string", "k8s 工作区快照 key 前缀"),
|
|
493
|
+
r("WORKSPACE_SNAPSHOT_TIMEOUT_MS", "orchestration", "number", `k8s 工作区快照的时限(毫秒,整数 [${WORKSPACE_SNAPSHOT_TIMEOUT_MS_RANGE.min}, ${WORKSPACE_SNAPSHOT_TIMEOUT_MS_RANGE.max}];域外拒启):一个数管四处 —— run 末上传与连沙箱时恢复的墙钟上界、空间结束时回收座一次调用的绝对截止(卷与对象都在内)、下一条 run 等上一条存完的最长等待(提交围栏的存活上界);大文件读写的墙钟也是它。大工作区(构建目录 GB 级)撞上界 ⇒ 调大它或配 WORKSPACE_SNAPSHOT_EXCLUDE`, { staticDefault: String(WORKSPACE_SNAPSHOT_TIMEOUT_MS_DEFAULT) }),
|
|
487
494
|
r("WORKSPACE_SNAPSHOT_TTL_SEC", "orchestration", "number", "k8s 工作区快照 presign TTL(秒)"),
|
|
488
495
|
r("WORKTREE_ALLOWED_ROOTS", "orchestration", "csv", "worktree 隔离纵深白名单(缺省 = [repoRoot])", { danger: SEC }),
|
|
489
496
|
r("WORKTREE_BASE_COMMIT", "orchestration", "string", "worktree 基准 ref(缺省 core HEAD)"),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DroppedConfigEntry, type UnreadConfigFile } from "./web-admin-client/read-warnings.js";
|
|
1
|
+
import { type DroppedConfigEntry, type RetiredDomainFinding, type UnreadConfigFile } from "./web-admin-client/read-warnings.js";
|
|
2
2
|
import { FileConfigStore } from "@sema-agent/settings-schema/node";
|
|
3
3
|
import { type EffectiveConfig as AgentConfigEffective, type EffectiveReadWarning } from "@sema-agent/settings-schema";
|
|
4
4
|
import { fetchEffective as remoteFetchEffective, fetchSkillContent as remoteFetchSkillContent, type EffectiveConfig } from "./web-admin-client/facade.js";
|
|
@@ -25,6 +25,9 @@ import type { ConfigProviderWord } from "./config-types.js";
|
|
|
25
25
|
* `effective.models.droppedCatalogEntries`(`GET /v1/models.droppedEntries` 的源,与 `models` 同世代)。 */
|
|
26
26
|
/** `unreadFiles`:`config.d` 里读腿根本不读的文件(不是域 / 不是便携域)—— **不**进候选门(不是读的域判形失败),调用方一份一行
|
|
27
27
|
* `config_unread_file` 点名、其余照用;缺席 = 没有(本地读腿才会有)。 */
|
|
28
|
+
/** `retiredDomains`(S-1456):带事实的退役域文档(契约包的墓碑)—— 读腿不抛,交成发现,候选判官以成因 `retired_domain` 整拒这份候选(与域判形失败
|
|
29
|
+
* 同一条回落链、同一行拒判);缺席 = 没有。远端腿:那一键不进 effective、其余域照读;本地腿:契约读腿在读便携域之前就拒,交出的候选只有版本
|
|
30
|
+
* (这棵树的内容版本,哈希含退役文件 ⇒ 改 / 删它版本即变),内容是空的 effective(被整拒,不会被应用)。 */
|
|
28
31
|
export type FetchEffectiveResult = {
|
|
29
32
|
effective: EffectiveConfig;
|
|
30
33
|
etag?: string;
|
|
@@ -34,6 +37,7 @@ export type FetchEffectiveResult = {
|
|
|
34
37
|
}>;
|
|
35
38
|
droppedEntries?: DroppedConfigEntry[];
|
|
36
39
|
unreadFiles?: UnreadConfigFile[];
|
|
40
|
+
retiredDomains?: RetiredDomainFinding[];
|
|
37
41
|
readWarnings: readonly EffectiveReadWarning[];
|
|
38
42
|
credentialIdentity?: string;
|
|
39
43
|
} | null;
|
package/dist/config-provider.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { readMcpSourceLabel } from "./mcp-source-label.js";
|
|
2
2
|
import { createHmac, randomBytes } from "node:crypto";
|
|
3
|
-
import { splitFoldedReadWarnings, withDroppedCatalogEntries } from "./web-admin-client/read-warnings.js";
|
|
3
|
+
import { retiredDomainFindingOf, splitFoldedReadWarnings, withDroppedCatalogEntries } from "./web-admin-client/read-warnings.js";
|
|
4
4
|
import { FileConfigStore } from "@sema-agent/settings-schema/node";
|
|
5
|
-
import { danglingRefs, findSkillContent, renderRefIssue, skillContentHash, } from "@sema-agent/settings-schema";
|
|
5
|
+
import { danglingRefs, emptyEffective, findSkillContent, renderRefIssue, skillContentHash, } from "@sema-agent/settings-schema";
|
|
6
6
|
import { redactSecrets } from "./trace/redact.js";
|
|
7
7
|
import { fetchEffective as remoteFetchEffective, fetchSkillContent as remoteFetchSkillContent, WebAdminHttpError, } from "./web-admin-client/facade.js";
|
|
8
8
|
import { homedir } from "node:os";
|
|
@@ -84,7 +84,21 @@ export class LocalConfigProvider {
|
|
|
84
84
|
readWarnings.push(w);
|
|
85
85
|
},
|
|
86
86
|
});
|
|
87
|
-
|
|
87
|
+
let read;
|
|
88
|
+
let retired;
|
|
89
|
+
try {
|
|
90
|
+
read = await store.getEffective({ tolerant: true });
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
retired = retiredDomainFindingOf(e);
|
|
94
|
+
if (retired === undefined)
|
|
95
|
+
throw e;
|
|
96
|
+
const version = await store.getVersion().catch(() => {
|
|
97
|
+
throw e;
|
|
98
|
+
});
|
|
99
|
+
read = { effective: { ...emptyEffective(), version }, domainErrors: [] };
|
|
100
|
+
}
|
|
101
|
+
const { effective: eff, domainErrors } = read;
|
|
88
102
|
const tag = String(eff.version);
|
|
89
103
|
if (etag !== undefined && etag === tag)
|
|
90
104
|
return null;
|
|
@@ -97,7 +111,7 @@ export class LocalConfigProvider {
|
|
|
97
111
|
}
|
|
98
112
|
for (const [domain, rows] of byReferrer)
|
|
99
113
|
refErrors.push({ domain, error: rows.join("; ") });
|
|
100
|
-
const folded = splitFoldedReadWarnings(readWarnings);
|
|
114
|
+
const folded = splitFoldedReadWarnings(readWarnings, "local");
|
|
101
115
|
const parseErrors = folded.domainErrors.map((w) => ({ domain: w.domain, error: redactConfigError(w.error) }));
|
|
102
116
|
const droppedEntries = folded.droppedEntries.map(redactDroppedEntry);
|
|
103
117
|
const errors = [...domainErrors.map((de) => ({ domain: de.domain, error: redactConfigError(de.error) })), ...parseErrors, ...refErrors];
|
|
@@ -108,6 +122,7 @@ export class LocalConfigProvider {
|
|
|
108
122
|
...(errors.length > 0 ? { domainErrors: errors } : {}),
|
|
109
123
|
...(droppedEntries.length > 0 ? { droppedEntries } : {}),
|
|
110
124
|
...(folded.unreadFiles.length > 0 ? { unreadFiles: folded.unreadFiles } : {}),
|
|
125
|
+
...(retired !== undefined ? { retiredDomains: [retired] } : {}),
|
|
111
126
|
};
|
|
112
127
|
}
|
|
113
128
|
async fetchSkillContent(contentHash) {
|
|
@@ -172,6 +187,9 @@ export function mapToServiceEffective(eff, version) {
|
|
|
172
187
|
...(s.contentOrigin !== undefined ? { contentOrigin: s.contentOrigin } : {}),
|
|
173
188
|
...readMcpSourceLabel(s.name, s.source),
|
|
174
189
|
...(s.toolFaces !== undefined ? { toolFaces: s.toolFaces } : {}),
|
|
190
|
+
...(s.toolAxes !== undefined ? { toolAxes: s.toolAxes } : {}),
|
|
191
|
+
...(s.authForm !== undefined ? { authForm: s.authForm } : {}),
|
|
192
|
+
...(s.entryKind !== undefined ? { entryKind: s.entryKind } : {}),
|
|
175
193
|
};
|
|
176
194
|
if (s.transport.kind === "stdio") {
|
|
177
195
|
return {
|
|
@@ -191,6 +209,7 @@ export function mapToServiceEffective(eff, version) {
|
|
|
191
209
|
url: s.transport.url,
|
|
192
210
|
...(s.transport.headerRefs !== undefined ? { headerRefs: s.transport.headerRefs } : {}),
|
|
193
211
|
...(s.transport.principalHeader !== undefined ? { principalHeader: s.transport.principalHeader } : {}),
|
|
212
|
+
...(s.transport.assertionHeader !== undefined ? { assertionHeader: s.transport.assertionHeader } : {}),
|
|
194
213
|
},
|
|
195
214
|
};
|
|
196
215
|
}),
|
package/dist/config-types.d.ts
CHANGED
|
@@ -604,7 +604,8 @@ export interface ServiceConfigFlat {
|
|
|
604
604
|
defaultScopes?: string[];
|
|
605
605
|
}>;
|
|
606
606
|
/** Role → model map (1.24): `subagent`/`summarize` → the cheap model when `MODEL_CHEAP_ID` is set
|
|
607
|
-
* (
|
|
607
|
+
* (delegated children + compaction get cheap), `default` stays on the main model. Keys are the engine's role
|
|
608
|
+
* words (core `MODEL_ROLES`, six since 7.49.0). */
|
|
608
609
|
roles: ModelRoles;
|
|
609
610
|
/** [ref] / [ref] —— **「`@` 能点名哪些模型」**(settings-schema 11 `models.atMention` 的服务端消费面;三态闭集
|
|
610
611
|
* `{mode:"all"}` / `{mode:"none"}` / `{mode:"only", models}`,形与缺省读法的属主是契约,本仓读法 = `model-select.ts`
|
|
@@ -898,6 +899,9 @@ export interface ServiceConfigFlat {
|
|
|
898
899
|
/** Resource-profile knobs: sandbox pod limits (adapter defaults: 2Gi / 1 cpu). */
|
|
899
900
|
memory?: string;
|
|
900
901
|
cpu?: string;
|
|
902
|
+
/** `K8S_SANDBOX_ENV=NAME,NAME` 点到、且本进程环境里真有的键 ⇒ 原值(与 e2b 的 `sandboxEnv` 同名同形、同一只解析器、同一只谓词 `allowlistedEnv`,
|
|
903
|
+
* 空串值照带)。只进 pod 容器 env;装配点与包源派生 env 合并一处,显式名单胜。键缺席 = 旋钮未设 / 空串(零转发)。 */
|
|
904
|
+
sandboxEnv?: Record<string, string>;
|
|
901
905
|
s3Snapshot?: {
|
|
902
906
|
endpoint: string;
|
|
903
907
|
bucket: string;
|
|
@@ -913,6 +917,15 @@ export interface ServiceConfigFlat {
|
|
|
913
917
|
* unavailable). */
|
|
914
918
|
workspacePersist?: import("./workspace-space.js").WorkspacePersist;
|
|
915
919
|
workspaceSnapshotKeep?: number;
|
|
920
|
+
/** `WORKSPACE_SNAPSHOT_TIMEOUT_MS` — the lane's one data bound (`workspace-space.ts`); the loader always mints it, the boot
|
|
921
|
+
* assembly hands it to the adapter as `dataTimeoutMs`, the capability fact reports it (`workspaceSync.timeoutMs`). */
|
|
922
|
+
workspaceSnapshotTimeoutMs?: number;
|
|
923
|
+
/** The build-cache volume per workspace space (`WORKSPACE_CACHE=volume`, `_SIZE`, `_MOUNT`; `workspace-cache.ts`); present iff
|
|
924
|
+
* `volume`. Effective policy = the capability fact `workspaceCache`. */
|
|
925
|
+
workspaceCache?: import("./workspace-cache.js").WorkspaceCacheCapability;
|
|
926
|
+
/** `WORKSPACE_SNAPSHOT_EXCLUDE` — the snapshot's tar exclusion table (closed item form, `workspace-space.ts`); present iff
|
|
927
|
+
* non-empty. Handed to the adapter's one tar upload (both snapshot lanes); never on the wire. */
|
|
928
|
+
workspaceSnapshotExclude?: readonly string[];
|
|
916
929
|
} | {
|
|
917
930
|
provider: "ssh";
|
|
918
931
|
host: string;
|
package/dist/config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { DEFAULT_AT_MENTION, DEFAULT_MODEL_REF } from "./model-select.js";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
4
|
+
import { join, posix as posixPath } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { BUILTIN_COMPLIANCE_DENIES, COMPLIANCE_CAPABILITIES, CROSS_SESSION_INBOUND_SETTINGS, CROSS_SESSION_DIALOG_EXPIRY_VALUES, compileReadDeny, resolveReadDenyBuiltins, CODE_AGENT_PROMPT, isModelPriced, PROTOCOL_TABLE, RECOMMENDED_SENSITIVE_PATTERNS, judgeRuleToolName, resolveFileHistoryRetention, resolveLockedKeys, validatePermissionRules, WRITE_PROTECTED_DEFAULT_TABLE, resolveWriteProtectedTable } from "@sema-agent/core";
|
|
7
7
|
import { ROSTER_PRIMARY_ROLES, ROSTER_CHEAP_ROLES, WEB_ADMIN_ENV, retiredEnvRefusal } from "@sema-agent/settings-schema";
|
|
@@ -26,7 +26,8 @@ import { describeUnmatchableRuleName, ruleEntryToolName, unmatchableRuleNameOf }
|
|
|
26
26
|
import { bakeOperatorPrincipalsRefusal, bakeRunnerCredentialRefusal, centerIdentityRefusal, halfOpenDirectDoorRefusal, leaderDurableStoreRefusal, operatorPrincipalsRequiredRefusal } from "./config-invariants.js";
|
|
27
27
|
import { declaredSemaConfigDir } from "./sema-config-dir.js";
|
|
28
28
|
import { lkgPathOverrideOf } from "./config-lkg.js";
|
|
29
|
-
import { WORKSPACE_PERSIST_DEFAULT, WORKSPACE_PERSIST_WORDS, WORKSPACE_SNAPSHOT_KEEP_DEFAULT, WORKSPACE_SNAPSHOT_KEEP_RANGE } from "./workspace-space.js";
|
|
29
|
+
import { K8S_WORKSPACE_MOUNT_DEFAULT, WORKSPACE_PERSIST_DEFAULT, WORKSPACE_PERSIST_WORDS, WORKSPACE_SNAPSHOT_KEEP_DEFAULT, WORKSPACE_SNAPSHOT_KEEP_RANGE, WORKSPACE_SNAPSHOT_TIMEOUT_MS_DEFAULT, WORKSPACE_SNAPSHOT_TIMEOUT_MS_RANGE, parseWorkspaceSnapshotExclude } from "./workspace-space.js";
|
|
30
|
+
import { WORKSPACE_CACHE_DEFAULT, WORKSPACE_CACHE_MOUNT_DEFAULT, WORKSPACE_CACHE_SIZE_DEFAULT, WORKSPACE_CACHE_WORDS, isK8sQuantity, mountsOverlap } from "./workspace-cache.js";
|
|
30
31
|
import { REMOTE_EXEC_PROVIDER_WORDS, executionLaneOf, executionLaneRequiredRefusal, isSingleMachineDefaultLane, laneRequiredEnv } from "./execution-lane-caps.js";
|
|
31
32
|
import { MEMORY_ENGINE_BACKENDS, SESSION_BACKENDS, STORE_BACKENDS } from "@sema-agent/settings-schema/execution-lanes";
|
|
32
33
|
import { AUTONOMY_MODES } from "./runtime-governance.js";
|
|
@@ -1855,7 +1856,9 @@ function parseOrchestrationDomain(ctx) {
|
|
|
1855
1856
|
...((n) => (n !== undefined ? { timeoutMs: n } : {}))(optNumEnvStrict("K8S_TIMEOUT_MS")),
|
|
1856
1857
|
...(process.env.K8S_MEMORY ? { memory: process.env.K8S_MEMORY } : {}),
|
|
1857
1858
|
...(process.env.K8S_CPU ? { cpu: process.env.K8S_CPU } : {}),
|
|
1859
|
+
...((names) => (names !== undefined ? { sandboxEnv: allowlistedEnv(names, process.env) } : {}))(parseEnvNameAllowlist("K8S_SANDBOX_ENV", singleUserTurnkey)),
|
|
1858
1860
|
...k8sWorkspaceStore(),
|
|
1861
|
+
...((c) => (c !== undefined ? { workspaceCache: c } : {}))(k8sWorkspaceCache()),
|
|
1859
1862
|
}
|
|
1860
1863
|
:
|
|
1861
1864
|
process.env.REMOTE_EXEC === "ssh" && process.env.SSH_HOST && process.env.SSH_USER && process.env.SSH_PRIVATE_KEY
|
|
@@ -2387,6 +2390,11 @@ function k8sWorkspaceStore() {
|
|
|
2387
2390
|
const workspaceSnapshotKeep = numEnvBounded("WORKSPACE_SNAPSHOT_KEEP", String(WORKSPACE_SNAPSHOT_KEEP_DEFAULT), WORKSPACE_SNAPSHOT_KEEP_RANGE.min, WORKSPACE_SNAPSHOT_KEEP_RANGE.max);
|
|
2388
2391
|
if (!Number.isInteger(workspaceSnapshotKeep))
|
|
2389
2392
|
throw new Error(`env WORKSPACE_SNAPSHOT_KEEP=${workspaceSnapshotKeep} must be an integer (a count of snapshots kept per space key)`);
|
|
2393
|
+
const workspaceSnapshotTimeoutMs = numEnvBounded("WORKSPACE_SNAPSHOT_TIMEOUT_MS", String(WORKSPACE_SNAPSHOT_TIMEOUT_MS_DEFAULT), WORKSPACE_SNAPSHOT_TIMEOUT_MS_RANGE.min, WORKSPACE_SNAPSHOT_TIMEOUT_MS_RANGE.max);
|
|
2394
|
+
if (!Number.isInteger(workspaceSnapshotTimeoutMs))
|
|
2395
|
+
throw new Error(`env WORKSPACE_SNAPSHOT_TIMEOUT_MS=${workspaceSnapshotTimeoutMs} must be an integer (milliseconds)`);
|
|
2396
|
+
const exclude = parseWorkspaceSnapshotExclude(process.env.WORKSPACE_SNAPSHOT_EXCLUDE);
|
|
2397
|
+
const knobs = { workspacePersist, workspaceSnapshotKeep, workspaceSnapshotTimeoutMs, ...(exclude.length > 0 ? { workspaceSnapshotExclude: exclude } : {}) };
|
|
2390
2398
|
const endpoint = process.env.MINIO_ENDPOINT;
|
|
2391
2399
|
const accessKey = process.env.MINIO_ACCESS_KEY;
|
|
2392
2400
|
const secretKey = process.env.MINIO_SECRET_KEY;
|
|
@@ -2396,14 +2404,13 @@ function k8sWorkspaceStore() {
|
|
|
2396
2404
|
CONFIG_NOTICES.push({
|
|
2397
2405
|
level: "warn",
|
|
2398
2406
|
event: "workspace_persist_unavailable",
|
|
2399
|
-
fields: { missing: missing.join(","), effect: "k8s workspace starts empty every run (no snapshot store); set the missing keys, or
|
|
2407
|
+
fields: { missing: missing.join(","), effect: "k8s workspace starts empty every run (no snapshot store); set the missing keys, or set WORKSPACE_PERSIST=off to silence this line" },
|
|
2400
2408
|
});
|
|
2401
2409
|
}
|
|
2402
|
-
return
|
|
2410
|
+
return knobs;
|
|
2403
2411
|
}
|
|
2404
2412
|
return {
|
|
2405
|
-
|
|
2406
|
-
workspaceSnapshotKeep,
|
|
2413
|
+
...knobs,
|
|
2407
2414
|
s3Snapshot: {
|
|
2408
2415
|
endpoint,
|
|
2409
2416
|
bucket: process.env.WORKSPACE_SNAPSHOT_BUCKET ?? "workspaces",
|
|
@@ -2415,6 +2422,32 @@ function k8sWorkspaceStore() {
|
|
|
2415
2422
|
},
|
|
2416
2423
|
};
|
|
2417
2424
|
}
|
|
2425
|
+
function k8sWorkspaceCache() {
|
|
2426
|
+
const word = enumEnv("WORKSPACE_CACHE", WORKSPACE_CACHE_DEFAULT, WORKSPACE_CACHE_WORDS);
|
|
2427
|
+
switch (word) {
|
|
2428
|
+
case "off":
|
|
2429
|
+
return undefined;
|
|
2430
|
+
case "volume":
|
|
2431
|
+
break;
|
|
2432
|
+
default: {
|
|
2433
|
+
const unreachable = word;
|
|
2434
|
+
throw new Error(`unhandled WORKSPACE_CACHE word: ${String(unreachable)}`);
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
const size = process.env.WORKSPACE_CACHE_SIZE || WORKSPACE_CACHE_SIZE_DEFAULT;
|
|
2438
|
+
if (!isK8sQuantity(size))
|
|
2439
|
+
throw new Error(`env WORKSPACE_CACHE_SIZE=${JSON.stringify(size)} is not a k8s quantity (a positive number with an optional unit, e.g. 20Gi / 500Mi)`);
|
|
2440
|
+
const raw = process.env.WORKSPACE_CACHE_MOUNT || WORKSPACE_CACHE_MOUNT_DEFAULT;
|
|
2441
|
+
if (!raw.startsWith("/"))
|
|
2442
|
+
throw new Error(`env WORKSPACE_CACHE_MOUNT=${JSON.stringify(raw)} is not an absolute path (the cache volume's mount inside the sandbox pod)`);
|
|
2443
|
+
const mount = posixPath.normalize(raw).replace(/(.)\/+$/, "$1");
|
|
2444
|
+
const workspace = posixPath.normalize(process.env.K8S_MOUNT_PATH || K8S_WORKSPACE_MOUNT_DEFAULT).replace(/(.)\/+$/, "$1");
|
|
2445
|
+
if (mount === "/" || mountsOverlap(mount, workspace)) {
|
|
2446
|
+
throw new Error(`env WORKSPACE_CACHE_MOUNT=${mount} overlaps the workspace mount ${workspace} (K8S_MOUNT_PATH) — the cache volume must sit OUTSIDE the workspace ` +
|
|
2447
|
+
"(the workspace is snapshotted between runs, the cache is not); pick a separate absolute path such as /cache");
|
|
2448
|
+
}
|
|
2449
|
+
return { mount, size };
|
|
2450
|
+
}
|
|
2418
2451
|
export function loadConfig() {
|
|
2419
2452
|
EXEC_LANE_NOTICE = undefined;
|
|
2420
2453
|
rejectRetiredEnvs();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FileError, StubExecutionEnv, type ExecutionEnv, type Result, type ToolPolicy } from "@sema-agent/core";
|
|
1
|
+
import { FileError, StubExecutionEnv, type ExecutionEnv, type PathFamily, type Result, type ToolPolicy } from "@sema-agent/core";
|
|
2
2
|
import { type DeploymentListExemption } from "./approval.js";
|
|
3
3
|
import type { ServiceConfig } from "./config.js";
|
|
4
4
|
import type { applyRuntimeGovernance } from "./runtime-governance.js";
|
|
@@ -15,8 +15,9 @@ export interface DeploymentGovernanceConfigView {
|
|
|
15
15
|
readonly agentConfigDir?: ServiceConfig["agentConfigDir"];
|
|
16
16
|
/**
|
|
17
17
|
* 本部署的**本地店根**(`LOCAL_DATA_ROOT → CONFIG_LOCAL_DIR → AGENT_DATA_DIR → ~/.ai-agent`)—— 在本口只喂
|
|
18
|
-
* **誊本门**(`<localDataRoot>/sessions`)。S-133
|
|
19
|
-
*
|
|
18
|
+
* **誊本门**(`<localDataRoot>/sessions`)。S-133 起它**不再**当守卫集的数据根(那是引擎记忆根);core 7.49.0 [ref] 起守卫集
|
|
19
|
+
* 根本不收数据根 —— 豁免根只从 `RunnerDeps.memoryEngineDir` 一处来(`boot/runner-deps.ts` 共享基座,每只 boot Runner 同一个值)。
|
|
20
|
+
* 下面这段历史注保留,记的是 S-125 件⑦ 把两根混作一根的由来。
|
|
20
21
|
*
|
|
21
22
|
* S-125 件⑦(core 7.4.0 [ref] HRD-PRM-10)—— 当时把本键原样交给 `createSensitivePathPolicy` 的 `dataRoot`。
|
|
22
23
|
*
|
|
@@ -28,21 +29,10 @@ export interface DeploymentGovernanceConfigView {
|
|
|
28
29
|
* ⇒ 本键 = 「这道门与 transcript 门说的是同一个目录」的单一属主,值与 `ServiceConfig.localDataRoot`
|
|
29
30
|
* **同一个**解析结果(不在本口重算,重算就是第二个写者)。
|
|
30
31
|
*
|
|
31
|
-
* 缺席(窄接口的老调用方 / 测试夹具)⇒
|
|
32
|
-
* `rootPath` 条件展开同姿势:缺席是「本调用方没有这项知识」,不是「数据根是 undefined」。
|
|
32
|
+
* 缺席(窄接口的老调用方 / 测试夹具)⇒ 不铸誊本门(缺席是「本调用方没有这项知识」,不是「店根是 undefined」)。
|
|
33
33
|
*/
|
|
34
34
|
readonly localDataRoot?: ServiceConfig["localDataRoot"];
|
|
35
35
|
}
|
|
36
|
-
/**
|
|
37
|
-
* S-133 —— 守卫集 `dataRoot` 的**显式供给**(与 `DeploymentGovernanceConfigView.localDataRoot` 是两件事):
|
|
38
|
-
* `engineDataRoot` = 引擎写记忆的根 = boot 已铸的 `memoryEngine.root`(boot/stores.ts 是唯一写者;推导函数
|
|
39
|
-
* `memoryEngineRootFor` 只在那里与 `memoryEngineBackendFor` 里调)。**调用腿读那只活对象,不重推导**——重推导
|
|
40
|
-
* 就是第二个写者(7.59.0 重扫 codex 轮抓到 HTTP 腿的 fallback 与 stores 不同源,正是这一形)。参数非可选:
|
|
41
|
-
* 一条腿忘了 = 编译红。`undefined` = 引擎未接(或窄接口的测试夹具),那时不铸 `dataRoot` 键,core 走自己的缺省。
|
|
42
|
-
*/
|
|
43
|
-
export interface DeploymentGovernanceRoots {
|
|
44
|
-
readonly engineDataRoot: string | undefined;
|
|
45
|
-
}
|
|
46
36
|
/** 审批基线读的配置切面(同上,窄接口)。 */
|
|
47
37
|
export interface ApprovalBaselineConfigView {
|
|
48
38
|
readonly approvalRequire: ServiceConfig["approvalRequire"];
|
|
@@ -175,18 +165,26 @@ export declare function createDurableQuestionGate(live: LiveQuestionFace | undef
|
|
|
175
165
|
* · 词法层(`RelativeTargetLexicalEnv`)判 **缺戳相对形**(自身拼写里的守卫段,fail-closed);
|
|
176
166
|
* 两层射程互补、无重叠、无缝隙;各自射程外**显式 allow**(= 让位给另一层),canon 失败留给真的判不了的形
|
|
177
167
|
* (UNC/NUL/越根)—— 那正是 7.17.1 要 deny 的。提取写目标用 core 自家 `protectivePathTargetOf` + `pathTargetValue`
|
|
178
|
-
* (与 core 守卫策略同一只提取器,零复刻);「算不算绝对」用 core `isAbsoluteForFamily(
|
|
179
|
-
*
|
|
168
|
+
* (与 core 守卫策略同一只提取器,零复刻);「算不算绝对」用 core `isAbsoluteForFamily(SANDBOX_TREE_FAMILY, …)` —— 两层读
|
|
169
|
+
* **同一只**谓词(词法层的 `absolutePath` 拒的正是这一形),射程因此按构造互补。
|
|
170
|
+
*/
|
|
171
|
+
/**
|
|
172
|
+
* 沙箱 lane 的树是 **POSIX** 树(core 7.49.0 [ref] 起 `isAbsoluteForFamily` 的族参数必写:树的族,或无树时的 `"own"`)。
|
|
173
|
+
* 沙箱的文件系统是远端容器 / 机器的 POSIX 文件系统,词法层也按 POSIX 归一(`posix.normalize`)—— 所以这里写树的族,而不是 `"own"`:
|
|
174
|
+
* `"own"` 会把 `C:\x` / UNC 拼法读成绝对形送进真身层,而在 POSIX 树上它们是**相对文件名**(写进 cwd 的一个叫 `C:\x` 的文件)。
|
|
175
|
+
* 7.48.0 的 `undefined` 只认 `/`-rooted,与本常量逐字同判(读数不变)。
|
|
180
176
|
*/
|
|
177
|
+
export declare const SANDBOX_TREE_FAMILY: PathFamily;
|
|
181
178
|
type WriteTargetForm = "unstamped-relative" | "absolute-or-stamped";
|
|
182
179
|
/**
|
|
183
180
|
* 只在 `form` 那一类写目标上说话,其余显式 allow(让位);非写调用与提不出目标的调用原样交给 policy(它自己判 allow)。
|
|
184
181
|
*
|
|
185
182
|
* 🔴 **S-877(core 7.35.0 #1200):本包装不是 `wrapToolPolicy`,它自报成员**。core 的 wrap 契约是「包装至少拒内层所拒」,
|
|
186
183
|
* 而本包装**放行**内层会拒的另一形写目标 ⇒ 按契约它是一只自己的策略,内层的成员不能照搬(core wire 单点名这一只):
|
|
187
|
-
* · `
|
|
188
|
-
* ({@link
|
|
189
|
-
*
|
|
184
|
+
* · `writeGuardRows`(core 7.49.0 [ref] 起;7.48.0 叫 `writeTargetGuard`,旧成员 core **不按名拒** ⇒ 不改就是壳写站静默丢部署守卫行)
|
|
185
|
+
* —— 守卫集策略自带,壳写站按它交出的行判绝对目标;只在本层的形**覆盖行的判定形**时带上({@link WRITE_GUARD_ROWS_DOMAIN}):
|
|
186
|
+
* 真身层带;词法层不带(它的行与真身层是同一张模式表,带上只是同一组行判两遍)。这不是给某一形开的特例,是同一条
|
|
187
|
+
* 「成员描述它守得住的那部分」的读法;
|
|
190
188
|
* · `projection` / `pathRules` / `nameSets` —— 守卫集策略不带,本包装也不报(报了就是替它声称一张它没有的拒表)。
|
|
191
189
|
* 修前(core 7.33.x)这里是一只 `{ check }` 字面量,7.34.0 起那只字面量把真身层的守卫剥掉了 —— 沙箱 lane 的 shell 写站
|
|
192
190
|
* 因此看不见部署守卫集(`cp x .env` 在 acceptEdits 下被引擎 place 并答掉)。
|
|
@@ -253,7 +251,7 @@ export declare function buildOnlySensitiveBaselineWarning(config: Pick<Deploymen
|
|
|
253
251
|
* 本口不知道出身这件事,也不再有自己的折叠点。叶的顺序 = 修前折叠的顺序(真身层 → 词法层 → 誊本门),deny 优先 / 首问 / 成员合并
|
|
254
252
|
* 的读法因此不变。
|
|
255
253
|
*/
|
|
256
|
-
export declare function createDeploymentGovernanceInputs(config: DeploymentGovernanceConfigView, pathAdjudication: PathAdjudication
|
|
254
|
+
export declare function createDeploymentGovernanceInputs(config: DeploymentGovernanceConfigView, pathAdjudication: PathAdjudication): DeploymentGovernanceInputs;
|
|
257
255
|
/**
|
|
258
256
|
* 运维 allow 表 `APPROVAL_GRANT` 的**起服通告**载荷(纯数据 ⇒ `build*`;HTTP 腿与 run-local 腿各在装配时说一次,用 info 级)。规则不是秘密
|
|
259
257
|
* (它们是工具名 / 命令规则),所以原样列出;空表 ⇒ `undefined`(不打)。运维只读面上同一个事实另有一处:`GET /v1/diagnostics/wiring` 的
|
|
@@ -16,6 +16,7 @@ export function createDurableQuestionGate(live) {
|
|
|
16
16
|
},
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
|
+
export const SANDBOX_TREE_FAMILY = "posix";
|
|
19
20
|
function writeTargetFormOf(req) {
|
|
20
21
|
if (!isProtectedWrite(req))
|
|
21
22
|
return undefined;
|
|
@@ -23,11 +24,11 @@ function writeTargetFormOf(req) {
|
|
|
23
24
|
const target = pt === undefined ? undefined : pathTargetValue(req.args, pt);
|
|
24
25
|
if (typeof target !== "string" || target.length === 0)
|
|
25
26
|
return undefined;
|
|
26
|
-
if (req.cwd !== undefined || target.includes("\u0000") || isAbsoluteForFamily(
|
|
27
|
+
if (req.cwd !== undefined || target.includes("\u0000") || isAbsoluteForFamily(SANDBOX_TREE_FAMILY, target))
|
|
27
28
|
return "absolute-or-stamped";
|
|
28
29
|
return "unstamped-relative";
|
|
29
30
|
}
|
|
30
|
-
const
|
|
31
|
+
const WRITE_GUARD_ROWS_DOMAIN = "absolute-or-stamped";
|
|
31
32
|
export function scopedToWriteTargetForm(policy, form) {
|
|
32
33
|
return {
|
|
33
34
|
async check(req, signal) {
|
|
@@ -36,12 +37,12 @@ export function scopedToWriteTargetForm(policy, form) {
|
|
|
36
37
|
return { action: "allow" };
|
|
37
38
|
return policy.check(req, signal);
|
|
38
39
|
},
|
|
39
|
-
...(form ===
|
|
40
|
+
...(form === WRITE_GUARD_ROWS_DOMAIN && policy.writeGuardRows !== undefined ? { writeGuardRows: policy.writeGuardRows } : {}),
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
43
|
export class RelativeTargetLexicalEnv extends StubExecutionEnv {
|
|
43
44
|
absolutePath(path) {
|
|
44
|
-
if (path.length === 0 || path
|
|
45
|
+
if (path.length === 0 || isAbsoluteForFamily(SANDBOX_TREE_FAMILY, path) || path.includes("\u0000")) {
|
|
45
46
|
return Promise.resolve(err(new FileError("not_supported", "this guard layer only adjudicates RELATIVE write targets (absolute forms are adjudicated against the real sandbox filesystem)", path)));
|
|
46
47
|
}
|
|
47
48
|
return Promise.resolve(ok(posix.normalize(`/${path}`)));
|
|
@@ -83,16 +84,14 @@ export function buildOnlySensitiveBaselineWarning(config, seat) {
|
|
|
83
84
|
},
|
|
84
85
|
};
|
|
85
86
|
}
|
|
86
|
-
export function createDeploymentGovernanceInputs(config, pathAdjudication
|
|
87
|
+
export function createDeploymentGovernanceInputs(config, pathAdjudication) {
|
|
87
88
|
const sensitivePathLayers = config.sensitiveWritePatterns.length > 0
|
|
88
89
|
? (() => {
|
|
89
|
-
const dataRootOpt = roots.engineDataRoot !== undefined ? { dataRoot: roots.engineDataRoot } : {};
|
|
90
90
|
const configRootOpt = config.agentConfigDir !== undefined ? { agentConfigDir: config.agentConfigDir } : {};
|
|
91
91
|
const realTarget = createSensitivePathPolicy({
|
|
92
92
|
env: pathAdjudication.env,
|
|
93
93
|
patterns: config.sensitiveWritePatterns,
|
|
94
94
|
...(pathAdjudication.cwd !== undefined ? { rootPath: pathAdjudication.cwd } : {}),
|
|
95
|
-
...dataRootOpt,
|
|
96
95
|
...configRootOpt,
|
|
97
96
|
});
|
|
98
97
|
const transcriptGuard = config.localDataRoot !== undefined ? [createTranscriptIntegrityPolicy({ sessionsDirs: [join(config.localDataRoot, "sessions")] })] : [];
|
|
@@ -100,7 +99,7 @@ export function createDeploymentGovernanceInputs(config, pathAdjudication, roots
|
|
|
100
99
|
return [realTarget, ...transcriptGuard];
|
|
101
100
|
return [
|
|
102
101
|
scopedToWriteTargetForm(realTarget, "absolute-or-stamped"),
|
|
103
|
-
scopedToWriteTargetForm(createSensitivePathPolicy({ env: new RelativeTargetLexicalEnv(), patterns: config.sensitiveWritePatterns, ...
|
|
102
|
+
scopedToWriteTargetForm(createSensitivePathPolicy({ env: new RelativeTargetLexicalEnv(), patterns: config.sensitiveWritePatterns, ...configRootOpt }), "unstamped-relative"),
|
|
104
103
|
...transcriptGuard,
|
|
105
104
|
];
|
|
106
105
|
})()
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
* · `example` 进拒句;
|
|
7
7
|
* · `multiTenant` = `REQUIRE_PRINCIPAL=true` 下名单作不作数 —— **只有服务进程读的旋钮有这一列**(姿态是服务进程的概念):
|
|
8
8
|
* - `LSP_ENV_ALLOW` ⇒ ignored:host 腿语言服务器在多租户姿态下本来就不起,名单无处作数,设了要说出来(S-699)。
|
|
9
|
-
* -
|
|
10
|
-
* 带外凭据(e2b / docker 车道本来就是多租户 fleet 的主形),与 LSP 那条「本机子进程」的形不同;多租户下起服说一句。
|
|
9
|
+
* - 三只沙箱名单(e2b / local-docker / k8s 各一只) ⇒ honored:S-713 照录修前语义(任何姿态下都转发),S-715 主会话裁定维持 —— 沙箱 env 是部署方为隔离沙箱显式配的
|
|
10
|
+
* 带外凭据(e2b / docker / k8s 车道本来就是多租户 fleet 的主形),与 LSP 那条「本机子进程」的形不同;多租户下起服说一句。
|
|
11
11
|
* · `BAKE_ENV_ALLOW`(S-684 残余,7.103.0)由 **bake-runner 进程**读(构建宿主守护进程:没有主体、没有租户 ⇒ 没有姿态列,
|
|
12
|
-
* 不进 {@link describeAllowlistPostures} 的姿态句)
|
|
12
|
+
* 不进 {@link describeAllowlistPostures} 的姿态句)。它与服务侧四只旋钮同一只解析器、同一只「点名放行」谓词、同一条「原文按凭据类」律。
|
|
13
13
|
* 表是 `Record<旋钮, …>`:闭集加一只旋钮而不补行 = 编译红;行形随读它的进程定(服务进程 ⇒ 必须写姿态列)。
|
|
14
14
|
*
|
|
15
15
|
* 🔴 **姿态列只在这里写一次**([ref];7.101.0 合并复审 O9):凡要对人说「多租户下哪只旋钮忽略、哪只照转发」的句子,一律取
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* 当场撒谎。为什么是纯叶:`config-catalog.ts` 被 `config.ts` 值引,表留在 `config.ts` 会成装载环。
|
|
19
19
|
*/
|
|
20
20
|
/** 服务进程(`config.ts` `loadConfig`)读的名单型旋钮 —— 有多租户姿态。 */
|
|
21
|
-
export type ServerEnvNameAllowlistKnob = "LSP_ENV_ALLOW" | "E2B_SANDBOX_ENV" | "DOCKER_SANDBOX_ENV";
|
|
21
|
+
export type ServerEnvNameAllowlistKnob = "LSP_ENV_ALLOW" | "E2B_SANDBOX_ENV" | "DOCKER_SANDBOX_ENV" | "K8S_SANDBOX_ENV";
|
|
22
22
|
/** bake-runner 进程(`bake-runner/main.ts` `loadEnv`)读的名单型旋钮 —— 构建宿主守护进程没有主体 / 租户,没有姿态。 */
|
|
23
23
|
export type RunnerEnvNameAllowlistKnob = "BAKE_ENV_ALLOW";
|
|
24
24
|
export type EnvNameAllowlistKnob = ServerEnvNameAllowlistKnob | RunnerEnvNameAllowlistKnob;
|
|
@@ -41,7 +41,7 @@ export type EnvNameAllowlistKnobTable = {
|
|
|
41
41
|
readonly [K in EnvNameAllowlistKnob]: K extends ServerEnvNameAllowlistKnob ? ServerEnvNameAllowlistKnobRow : RunnerEnvNameAllowlistKnobRow;
|
|
42
42
|
};
|
|
43
43
|
export declare const ENV_NAME_ALLOWLIST_KNOBS: EnvNameAllowlistKnobTable;
|
|
44
|
-
/** 名单型旋钮的全部名字(
|
|
44
|
+
/** 名单型旋钮的全部名字(五只;表键派生)—— 两处用:解析器的「点名名单型旋钮 = 形错」、剥除的「名单原文按凭据类」臂。 */
|
|
45
45
|
export declare const ENV_NAME_ALLOWLIST_KNOB_NAMES: ReadonlySet<string>;
|
|
46
46
|
/**
|
|
47
47
|
* 多租户姿态句 —— **由表派生**,不许在别处手写。形:`under REQUIRE_PRINCIPAL=true: <旋钮> is ignored; <旋钮> / <旋钮> are forwarded as configured`
|
|
@@ -5,6 +5,7 @@ export const ENV_NAME_ALLOWLIST_KNOBS = {
|
|
|
5
5
|
},
|
|
6
6
|
E2B_SANDBOX_ENV: { example: "E2B_SANDBOX_ENV=GIT_TOKEN,NPM_TOKEN", multiTenant: { kind: "honored" } },
|
|
7
7
|
DOCKER_SANDBOX_ENV: { example: "DOCKER_SANDBOX_ENV=GIT_TOKEN,NPM_TOKEN", multiTenant: { kind: "honored" } },
|
|
8
|
+
K8S_SANDBOX_ENV: { example: "K8S_SANDBOX_ENV=GIT_TOKEN,NPM_TOKEN", multiTenant: { kind: "honored" } },
|
|
8
9
|
BAKE_ENV_ALLOW: { example: "BAKE_ENV_ALLOW=REGISTRY_PASSWORD,NPM_TOKEN" },
|
|
9
10
|
};
|
|
10
11
|
export const ENV_NAME_ALLOWLIST_KNOB_NAMES = new Set(Object.keys(ENV_NAME_ALLOWLIST_KNOBS));
|
|
@@ -56,7 +56,7 @@ export function executionLaneCaps(lane) {
|
|
|
56
56
|
memoryPersistenceCapable: NO,
|
|
57
57
|
hostFilePlane: NO,
|
|
58
58
|
coreRemoteExecutionEnv: YES,
|
|
59
|
-
canonicalPathAuthority:
|
|
59
|
+
canonicalPathAuthority: YES,
|
|
60
60
|
tenantSeparation: executionLaneRow(lane).tenantSeparation,
|
|
61
61
|
};
|
|
62
62
|
case "k8s":
|
|
@@ -128,7 +128,7 @@ export function executionLaneCaps(lane) {
|
|
|
128
128
|
memoryPersistenceCapable: NO,
|
|
129
129
|
hostFilePlane: NO,
|
|
130
130
|
coreRemoteExecutionEnv: YES,
|
|
131
|
-
canonicalPathAuthority:
|
|
131
|
+
canonicalPathAuthority: YES,
|
|
132
132
|
tenantSeparation: executionLaneRow(lane).tenantSeparation,
|
|
133
133
|
};
|
|
134
134
|
case "device":
|