@sema-agent/server 7.131.0 → 7.132.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 +309 -0
- package/README.md +5 -1
- package/README.zh-CN.md +3 -1
- package/USAGE.md +163 -54
- package/dist/approval-card.d.ts +3 -1
- package/dist/approval-card.js +2 -3
- package/dist/audit.d.ts +7 -10
- package/dist/auth-bridge.d.ts +4 -0
- package/dist/auth-bridge.js +10 -11
- package/dist/boot/deployment-mods.d.ts +31 -0
- package/dist/boot/deployment-mods.js +26 -0
- package/dist/boot/execution-env.d.ts +1 -1
- package/dist/boot/execution-env.js +19 -6
- package/dist/boot/memory-boundary.d.ts +2 -2
- package/dist/boot/read-deny-anchor-audit.d.ts +17 -0
- package/dist/boot/read-deny-anchor-audit.js +36 -0
- package/dist/boot/resolve-spec.d.ts +1 -5
- package/dist/boot/resolve-spec.js +19 -47
- package/dist/boot/runner-deps.d.ts +19 -8
- package/dist/boot/runner-deps.js +14 -2
- package/dist/boot/session-faces.d.ts +1 -7
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +4 -4
- package/dist/boot/stage-05-execution-env.js +7 -10
- package/dist/boot/stage-06-runners.d.ts +2 -2
- package/dist/boot/stage-06-runners.js +5 -4
- package/dist/boot/stage-07-capability-layer.d.ts +2 -2
- package/dist/boot/stage-07-capability-layer.js +3 -3
- package/dist/boot/stage-08-reapers.d.ts +2 -2
- package/dist/boot/stage-09-leader.d.ts +3 -9
- package/dist/boot/stage-10-http-server.d.ts +3 -9
- package/dist/boot/stage-10-http-server.js +6 -7
- package/dist/boot/stores.d.ts +1 -1
- package/dist/boot/stores.js +5 -6
- package/dist/boot/web-admin.d.ts +0 -3
- package/dist/boot/web-admin.js +35 -35
- package/dist/brain.js +17 -22
- package/dist/budget.js +5 -4
- package/dist/caller-text-echo.d.ts +20 -0
- package/dist/caller-text-echo.js +24 -0
- package/dist/capabilities/brand-identity.d.ts +26 -0
- package/dist/capabilities/brand-identity.js +27 -0
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/center-prompts.d.ts +32 -59
- package/dist/capabilities/center-prompts.js +18 -32
- package/dist/capabilities/engine-capabilities.js +2 -1
- package/dist/capabilities/hands-lane.d.ts +9 -6
- package/dist/capabilities/hands-lane.js +1 -1
- package/dist/capabilities/mcp-probe.d.ts +14 -1
- package/dist/capabilities/mcp-probe.js +22 -133
- package/dist/capabilities/scenarios.d.ts +34 -40
- package/dist/capabilities/scenarios.js +16 -33
- package/dist/capabilities/skills.d.ts +19 -4
- package/dist/capabilities/skills.js +30 -10
- package/dist/config-catalog.js +6 -6
- package/dist/config-lkg.d.ts +9 -9
- package/dist/config-lkg.js +20 -4
- package/dist/config-provider.d.ts +3 -1
- package/dist/config-provider.js +12 -4
- package/dist/config-types.d.ts +7 -9
- package/dist/config.js +17 -4
- package/dist/device-ws-protocol.d.ts +1 -1
- package/dist/device-ws-protocol.js +1 -0
- package/dist/env-name-allowlist-knobs.d.ts +12 -2
- package/dist/env-name-allowlist-knobs.js +5 -4
- package/dist/exec-bounds.d.ts +15 -3
- package/dist/exec-bounds.js +4 -0
- package/dist/execution-lane-caps.d.ts +9 -2
- package/dist/execution-lane-caps.js +11 -0
- package/dist/hooks/classic-stations.d.ts +86 -0
- package/dist/hooks/classic-stations.js +27 -0
- package/dist/hooks/hook-llm.d.ts +8 -5
- package/dist/hooks/hook-llm.js +78 -35
- package/dist/hooks/hook-runner.d.ts +232 -80
- package/dist/hooks/hook-runner.js +218 -312
- package/dist/http/admission.d.ts +8 -2
- package/dist/http/admission.js +101 -57
- package/dist/http/approval-sweeps.js +57 -16
- package/dist/http/checkpoint-ctx.d.ts +25 -8
- package/dist/http/checkpoint-ctx.js +11 -7
- package/dist/http/claimed-run.d.ts +13 -0
- package/dist/http/claimed-run.js +15 -0
- package/dist/http/device-placement.js +5 -10
- package/dist/http/dispatch.d.ts +0 -4
- package/dist/http/dispatch.js +5 -9
- package/dist/http/durable-run-leg.d.ts +2 -1
- package/dist/http/durable-run-leg.js +5 -3
- package/dist/http/health-self-report.d.ts +7 -5
- package/dist/http/health-self-report.js +4 -18
- package/dist/http/principal-gate.d.ts +23 -6
- package/dist/http/principal-gate.js +24 -5
- package/dist/http/refusal-body.d.ts +21 -0
- package/dist/http/refusal-body.js +4 -0
- package/dist/http/request-guards.d.ts +27 -0
- package/dist/http/request-guards.js +24 -3
- package/dist/http/resume-legs.d.ts +25 -0
- package/dist/http/resume-legs.js +43 -22
- package/dist/http/routes/capabilities.js +1 -1
- package/dist/http/routes/diagnostics.js +1 -1
- package/dist/http/routes/rules.js +2 -2
- package/dist/http/routes/runs.js +7 -7
- package/dist/http/routes/session-sync.js +4 -2
- package/dist/http/routes/sessions.js +1 -1
- package/dist/http/routes/shared-memory.js +2 -13
- package/dist/http/routes/side-query.js +2 -3
- package/dist/http/routes/tasks.js +19 -9
- package/dist/http/send.d.ts +9 -7
- package/dist/http/send.js +7 -2
- package/dist/http/server.d.ts +21 -11
- package/dist/http/server.js +28 -2
- package/dist/http/submit-ctx.d.ts +25 -0
- package/dist/http/submit-ctx.js +39 -0
- package/dist/http/wire-types.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lane-home-probe.d.ts +43 -0
- package/dist/lane-home-probe.js +35 -0
- package/dist/limit-refusal.d.ts +47 -0
- package/dist/limit-refusal.js +12 -0
- package/dist/main.js +1 -1
- package/dist/mcp-assertion-header.d.ts +1 -9
- package/dist/mcp-assertion-header.js +0 -6
- package/dist/mcp-tool-faces.d.ts +5 -0
- package/dist/mcp-tool-faces.js +5 -1
- package/dist/memory-scope.d.ts +1 -1
- package/dist/model-provider.d.ts +39 -12
- package/dist/model-provider.js +19 -2
- package/dist/model-route-endpoint.d.ts +1 -1
- package/dist/model-route-endpoint.js +5 -5
- package/dist/observability/cost-taxonomy.d.ts +7 -7
- package/dist/observability/fail-open.d.ts +42 -6
- package/dist/observability/fail-open.js +42 -6
- package/dist/observability/metrics.js +3 -1
- package/dist/observability/prompt-manifest.d.ts +47 -82
- package/dist/observability/prompt-manifest.js +119 -17
- package/dist/observability/run-terminal.js +14 -6
- package/dist/observability/secret-env-scrub.d.ts +13 -1
- package/dist/observability/secret-env-scrub.js +13 -1
- package/dist/observability/tool-trace.d.ts +16 -21
- package/dist/observability/tool-trace.js +51 -42
- package/dist/per-task-image.d.ts +7 -1
- package/dist/per-task-image.js +3 -3
- package/dist/plain-string-record.d.ts +25 -0
- package/dist/plain-string-record.js +32 -0
- package/dist/plugins/blob-backend.d.ts +68 -13
- package/dist/plugins/blob-backend.js +53 -10
- package/dist/plugins/checkpoint-store-sql.d.ts +14 -4
- package/dist/plugins/checkpoint-store-sql.js +39 -26
- package/dist/plugins/k8s-bg-scripts.d.ts +11 -0
- package/dist/plugins/k8s-bg-scripts.js +22 -0
- package/dist/plugins/local-checkpoint-store.js +5 -2
- package/dist/plugins/local-session-store.js +1 -1
- package/dist/plugins/one-time-migrations.d.ts +137 -90
- package/dist/plugins/one-time-migrations.js +356 -207
- package/dist/plugins/permission-rule-store-sql.d.ts +13 -7
- package/dist/plugins/permission-rule-store-sql.js +4 -18
- package/dist/plugins/pg-session-storage.d.ts +4 -5
- package/dist/plugins/pg-session-storage.js +7 -17
- package/dist/plugins/remote-env-adb.d.ts +6 -0
- package/dist/plugins/remote-env-adb.js +9 -4
- package/dist/plugins/remote-env-device.js +3 -0
- package/dist/plugins/remote-env-e2b.d.ts +1 -1
- package/dist/plugins/remote-env-e2b.js +21 -9
- package/dist/plugins/remote-env-host.d.ts +9 -9
- package/dist/plugins/remote-env-host.js +10 -32
- package/dist/plugins/remote-env-k8s.d.ts +95 -26
- package/dist/plugins/remote-env-k8s.js +265 -90
- package/dist/plugins/remote-env-local-docker.d.ts +20 -1
- package/dist/plugins/remote-env-local-docker.js +77 -9
- package/dist/plugins/remote-env-ssh.d.ts +15 -0
- package/dist/plugins/remote-env-ssh.js +109 -3
- package/dist/plugins/remote-shell.d.ts +0 -1
- package/dist/plugins/remote-shell.js +1 -2
- package/dist/plugins/retention-store-sql.js +6 -2
- package/dist/plugins/schema-consistency.d.ts +54 -0
- package/dist/plugins/schema-consistency.js +52 -0
- package/dist/plugins/session-epoch-anchor.d.ts +13 -0
- package/dist/plugins/session-epoch-anchor.js +23 -0
- package/dist/plugins/shared-memory-store-sql.d.ts +9 -3
- package/dist/plugins/shared-memory-store-sql.js +5 -16
- package/dist/plugins/sql-driver.d.ts +141 -0
- package/dist/plugins/sql-driver.js +115 -1
- package/dist/plugins/sql-errors.d.ts +41 -0
- package/dist/plugins/sql-errors.js +36 -0
- package/dist/plugins/store-backend.js +2 -1
- package/dist/plugins/tidb-session-storage.d.ts +7 -11
- package/dist/plugins/tidb-session-storage.js +6 -16
- package/dist/plugins/tidb-session-store.js +1 -1
- package/dist/prompts-domain-validate.d.ts +17 -61
- package/dist/prompts-domain-validate.js +9 -119
- package/dist/request-key-closure.d.ts +2 -2
- package/dist/request-key-closure.js +2 -4
- package/dist/rule-entry-list.d.ts +12 -9
- package/dist/rule-entry-list.js +37 -21
- package/dist/run-local.js +19 -19
- package/dist/runs.d.ts +6 -0
- package/dist/runs.js +16 -0
- package/dist/server-secret-env.d.ts +44 -18
- package/dist/server-secret-env.js +49 -8
- package/dist/session-incarnation.d.ts +15 -5
- package/dist/session-incarnation.js +16 -9
- package/dist/session-titler.js +12 -2
- package/dist/spec-fields.d.ts +28 -16
- package/dist/spec-fields.js +46 -53
- package/dist/sql-engine-posture.d.ts +29 -4
- package/dist/sql-engine-posture.js +36 -1
- package/dist/stored-request-tool-axes-m19.d.ts +19 -4
- package/dist/stored-request-tool-axes-m19.js +30 -2
- package/dist/task-a2a.d.ts +9 -1
- package/dist/task-a2a.js +73 -47
- package/dist/task-mcp.d.ts +46 -58
- package/dist/task-mcp.js +99 -65
- package/dist/task-settings.d.ts +7 -21
- package/dist/task-settings.js +7 -36
- package/dist/text-bidi.d.ts +3 -46
- package/dist/text-bidi.js +3 -3
- package/dist/tool-approval.d.ts +1 -1
- package/dist/trace/core-keyset-guard.d.ts +24 -4
- package/dist/trace/engine-notice-wire.d.ts +11 -3
- package/dist/trace/engine-notice-wire.js +8 -1
- package/dist/trace/ledger-events.d.ts +3 -1
- package/dist/trace/ledger-sink.js +4 -1
- package/dist/trace/model-segment.js +1 -1
- package/dist/trace/project.d.ts +19 -6
- package/dist/trace/project.js +57 -22
- package/dist/trace/wire-projection-faces.d.ts +79 -1
- package/dist/trace/wire-projection-faces.js +22 -0
- package/dist/web-admin-client/candidate-gate.d.ts +6 -6
- package/dist/web-admin-client/candidate-gate.js +3 -3
- package/dist/web-admin-client/http-client.js +0 -6
- package/dist/web-admin-client/read-warnings.d.ts +13 -0
- package/dist/web-admin-client/read-warnings.js +10 -0
- package/dist/web-admin-client/skills-mcp.d.ts +3 -0
- package/dist/web-admin-client/skills-mcp.js +9 -6
- package/dist/web-admin-client/types.d.ts +2 -3
- package/dist/workspace-cache.d.ts +35 -0
- package/dist/workspace-cache.js +36 -0
- package/dist/workspace-space.d.ts +3 -2
- package/dist/workspace-space.js +2 -0
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +8 -1
- package/package.json +4 -4
- package/scripts/drain-check-local.mjs +34 -1
- package/scripts/drain-check.mysql.sql +30 -2
- package/scripts/drain-check.pg.sql +29 -2
- package/dist/capabilities/memory-notice.d.ts +0 -138
- package/dist/capabilities/memory-notice.js +0 -64
- package/dist/capabilities/prompt.d.ts +0 -17
- package/dist/capabilities/prompt.js +0 -6
- package/dist/mcp-content-origin.d.ts +0 -34
- package/dist/mcp-content-origin.js +0 -10
- package/dist/tool-axis-words.d.ts +0 -27
- package/dist/tool-axis-words.js +0 -9
- package/dist/wire-name-bound.d.ts +0 -14
- package/dist/wire-name-bound.js +0 -13
package/dist/config-catalog.js
CHANGED
|
@@ -164,7 +164,7 @@ export const CONFIG_CATALOG = [
|
|
|
164
164
|
r("GIT_API_BASEURL", "integrations", "url", "repo 工具的 Git host API base", { configKey: "gitApiBaseUrl" }),
|
|
165
165
|
r("GIT_API_KIND", "integrations", "enum", "Git host API 方言", { enumValues: ["gitea", "github"], staticDefault: "gitea", configKey: "gitApiKind" }),
|
|
166
166
|
r("GIT_API_TOKEN", "integrations", "secret", "repo 工具的 Git host 凭据", { danger: SEC }),
|
|
167
|
-
r("HOOKS_TIMEOUT_MS", "orchestration", "number", "
|
|
167
|
+
r("HOOKS_TIMEOUT_MS", "orchestration", "number", "请求 settings.hooks 注册每个 handler 的时间预算(ms;0=零预算是合法值)", { derivedDefaultNote: "缺席 ⇒ 不铸键,读法 settingsHooksBudgetMs 取 600000" }),
|
|
168
168
|
r("HOST_BG_DEFAULT_TIMEOUT_SEC", "orchestration", "number", "host 后台 shell 缺省超时(秒)", { staticDefault: "300" }),
|
|
169
169
|
r("HOST_BG_ENABLED", "orchestration", "boolean", "host 车道后台 shell 开关", { staticDefault: "true" }),
|
|
170
170
|
r("HOST_BG_FILE_CAP", "orchestration", "number", "host 后台 shell 磁盘护栏(字节;失控输出被 reap)", { staticDefault: String(64 * 1024 * 1024) }),
|
|
@@ -225,7 +225,7 @@ export const CONFIG_CATALOG = [
|
|
|
225
225
|
r("LOCKED_CONFIG_KEYS", "auth", "csv", "管理员锁定层声明(词表=core 闭集注册表,未知键拒启)", { danger: SEC, configKey: "lockedConfigKeys" }),
|
|
226
226
|
r("LOG_LEVEL", "observability", "string", "日志档位", { staticDefault: "info", configKey: "logLevel" }),
|
|
227
227
|
r("LSP_ENABLED", "orchestration", "boolean", "LSP 沙箱腿 opt-in —— 本版 e2b / k8s 执行环境不实现绑定读,开了也不挂(起服一行 lsp_not_mounted);host 腿另有 LSP_HOST_ENABLED", { staticDefault: "false", configKey: "lspEnabled" }),
|
|
228
|
-
r("LSP_ENV_ALLOW", "orchestration", "secret", `host 腿语言服务器子进程 env 的点名放行名单(点到的键从服务 env 原样放回、部署方显式承担;没点到的照剥;与 host shell inheritEnv:[names] 同一只谓词;形错 / 点名任一只名单型旋钮(含自己)拒启且不回显值;本进程环境里没有的名按序号 warn、不放行、不回显;多租户姿态(忽略时起服 warn 一次):${describeAllowlistPostures()};原文按凭据类对待:只回在场位、不进任何子进程,生效名单见起服披露行 allowed)`, { danger: SEC, derivedDefaultNote: "缺席 / 空串 ⇒ 空名单 = 全剥(7.100.0 行为)" }),
|
|
228
|
+
r("LSP_ENV_ALLOW", "orchestration", "secret", `host 腿语言服务器子进程 env 的点名放行名单(点到的键从服务 env 原样放回、部署方显式承担;没点到的照剥;与 host shell inheritEnv:[names] 同一只谓词;形错 / 点名任一只名单型旋钮(含自己)/ 点名本服务自有凭据名(剥后放回会把引擎刚扣下的凭据交回去;判官 = 引擎拒白名单的同一只)拒启且不回显值;本进程环境里没有的名按序号 warn、不放行、不回显;多租户姿态(忽略时起服 warn 一次):${describeAllowlistPostures()};原文按凭据类对待:只回在场位、不进任何子进程,生效名单见起服披露行 allowed)`, { danger: SEC, derivedDefaultNote: "缺席 / 空串 ⇒ 空名单 = 全剥(7.100.0 行为)" }),
|
|
229
229
|
r("LSP_HOST_ENABLED", "orchestration", "boolean", "LSP host 腿开关(本机 language server,优雅降级)", { staticDefault: "true", configKey: "lspHostEnabled" }),
|
|
230
230
|
r("MANUAL_MODE_SHELL_GATE", "approval", "enum", "手动模式 shell 门收紧腿(off=no-op 非放松 —— 本键只有收紧半场;拼错拒启;S-877 起 classify 退役 = 拒启指路)", { danger: SEC, enumValues: ["always", "off"], echoWords: ["always"], resolve: (c) => c.manualModeShellGate ?? null, derivedDefaultNote: "off/未设 ⇒ 本键不贡献任何东西(归一成键缺席)⇒ 回显 null;真姿态只有 always 一个(core 7.34.0 起形状档在每一种模式下都装,classify 不再是运维选的档)" }),
|
|
231
231
|
r("MAX_PRINCIPAL_COST_USD", "limitsHttp", "number", "per-principal 窗内成本天花板(0=关)", { staticDefault: "0", danger: BILL, configKey: "maxPrincipalCostUsd", center: cLimits("maxPrincipalCostUsd") }),
|
|
@@ -384,7 +384,7 @@ export const CONFIG_CATALOG = [
|
|
|
384
384
|
r("REAP_INTERVAL_SEC", "limitsHttp", "number", "reaper 周期(秒)", { staticDefault: "60", configKey: "reapIntervalSec" }),
|
|
385
385
|
r("REAP_RUN_STALE_SEC", "limitsHttp", "number", "run 活性判陈旧阈(秒)", { staticDefault: "120", configKey: "runStaleSec", center: cLimits("runStaleSec") }),
|
|
386
386
|
r("REMOTE_EXEC", "orchestration", "enum", "执行车道选择(点名而配不齐/认不出 ⇒ 拒启,绝不静默降级到 host/stub)", { enumValues: REMOTE_EXEC_PROVIDER_WORDS, danger: SEC, derivedDefaultNote: "缺席:CONFIG_PROVIDER=local ⇒ host;其余 ⇒ 进程内 stub(手带整族不挂;残余名册看活体 wiring_manifest 里 mountedBy=hands 的条目数,不按工具名点。想让这一形拒启见 REQUIRE_EXECUTION_LANE)", configKey: "remoteExec", resolve: (c) => c.remoteExec?.provider ?? null }),
|
|
387
|
-
r("REMOTE_EXEC_HOME_DIR", "orchestration", "path", "执行环境的 home 目录(`~/`
|
|
387
|
+
r("REMOTE_EXEC_HOME_DIR", "orchestration", "path", "执行环境的 home 目录(`~/` 形权限规则的基、引擎家锚拒读行的落点;core ExecutionEnv.homeDir 座)。local-docker / ssh 车道在每只执行环境开起来时与它的 $HOME 对证,不一致或问不出 ⇒ 那只环境不开", { danger: SEC, derivedDefaultNote: "缺席:host/in-process ⇒ os.homedir();e2b ⇒ /home/user;k8s/local-docker/ssh/adb/device ⇒ 无(`~/` 规则 422 响亮拒;泄内容的递归读全 shell 面真人问、只读面拒;起服 warn execution_lane_home_undeclared)", configKey: "remoteExecHomeDir", resolve: (c) => c.remoteExecHomeDir ?? null }),
|
|
388
388
|
r("REQUIRE_EXECUTION_LANE", "orchestration", "boolean", "开了之后:REMOTE_EXEC 未点名 ∧ CONFIG_PROVIDER≠local ⇒ **拒启**并点名该设什么。默认关 = 照旧启动,但执行环境是进程内 stub、**零手带工具**(手带整族不挂;活体读数:mountedBy=hands 条目 10 → 0),名册里其余工具照常执行,任务仍回 status=completed —— 凡需要手的请求,与「模型不肯用工具」在用户面同形。判据 = 活体 wiring_manifest 里 mountedBy=hands 的条目数,不按工具名点;名册总条数随 core 版本走,不写死。托管/云部署推荐开(docs/DEPLOY-PREREQS.md)", { staticDefault: "false", danger: SEC, configKey: "requireExecutionLane" }),
|
|
389
389
|
r("REQUIRE_PRINCIPAL", "auth", "boolean", "多租户开关(posture 判别位:true ⇒ CC 能力族默认收紧)", { staticDefault: "false", danger: SEC, configKey: "requirePrincipal" }),
|
|
390
390
|
r("RESOURCE_SUSPEND", "approval", "boolean", "durable 路径 opt-in core resourceSuspend(预算/preempt ⇒ 可恢复挂起)", { staticDefault: "false", configKey: "resourceSuspend" }),
|
|
@@ -449,7 +449,7 @@ export const CONFIG_CATALOG = [
|
|
|
449
449
|
r("SIGHUP_IDLE_GRACE_MS", "limitsHttp", "number", "SIGHUP 空闲关停窗(ms;共享引擎形防误杀)", { staticDefault: "120000", configKey: "sighupIdleGraceMs" }),
|
|
450
450
|
r("SKILLS_DIR", "integrations", "path", "出厂 skill 目录(设了就整个替换包内 skills/,不叠加;配置源的技能再按名盖上)", { derivedDefaultNote: "缺席 ⇒ 包内 skills/(相对模块解析,不是 cwd)", configKey: "skillsDir" }),
|
|
451
451
|
r("SNAPSHOT_BLOB_ALLOW_SQL_BYTES", "store", "boolean", "云形缺 MinIO 时显式接受 SQL 店放快照字节(严格 'true';安全姿势开关不收宽松真值)", { staticDefault: "false", danger: DATA, configKey: "snapshotBlobAllowSql" }),
|
|
452
|
-
r("SNAPSHOT_BLOB_SQL_MAX_BYTES", "store", "number", "SQL 店单 blob 帽(字节)", { derivedDefaultNote: "缺席:mysql 引擎 ⇒
|
|
452
|
+
r("SNAPSHOT_BLOB_SQL_MAX_BYTES", "store", "number", "SQL 店单 blob 帽(字节)", { derivedDefaultNote: "缺席:mysql 引擎 ⇒ 库报的单行上限与 max_allowed_packet ÷ 2 取小(两堵墙各自读不到时按该库族文档缺省);pg ⇒ 不设", configKey: "snapshotBlobSqlMaxBytes" }),
|
|
453
453
|
r("SSH_HOST", "orchestration", "string", "ssh 车道目标主机(必需件)"),
|
|
454
454
|
r("SSH_HOST_FINGERPRINT", "orchestration", "string", "主机密钥指纹校验(坏值拒启;仅 ssh 车道被选中时求值)", { danger: SEC }),
|
|
455
455
|
r("SSH_KNOWN_HOSTS", "orchestration", "path", "known_hosts 路径(坏路径拒启)", { danger: SEC }),
|
|
@@ -499,12 +499,12 @@ export const CONFIG_CATALOG = [
|
|
|
499
499
|
r("WORKFLOW_SIZE_GUIDELINE", "orchestration", "enum", "Workflow 工具卡的规模建议(advisory;typo 拒启)", { enumValues: ["small", "medium", "large", "unrestricted"], configKey: "workflowSizeGuideline" }),
|
|
500
500
|
r("WORKFLOW_TOTAL_TIMEOUT_MS", "orchestration", "number", "workflow 脚本总时限(ms;0/负不是禁用 —— 无禁用臂)", { staticDefault: "3600000" }),
|
|
501
501
|
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 }),
|
|
502
|
-
r("WORKSPACE_CACHE_MOUNT", "orchestration", "path", "k8s 构建缓存卷在沙箱 pod 里的挂载点(绝对路径;与工作区挂载 K8S_MOUNT_PATH 相同 / 互相嵌套 ⇒
|
|
502
|
+
r("WORKSPACE_CACHE_MOUNT", "orchestration", "path", "k8s 构建缓存卷在沙箱 pod 里的挂载点(绝对路径;与工作区挂载 K8S_MOUNT_PATH 相同 / 互相嵌套 ⇒ 拒启;落在保留的镜像目录闭集上 / 之下 / 之上 ⇒ 拒启并点名那一项 —— /bin /boot /dev /etc /home/sandbox /lib /lib64 /opt/sema /proc /root /run /sbin /sys /tmp /usr /var;只在 WORKSPACE_CACHE=volume 时读)", { staticDefault: WORKSPACE_CACHE_MOUNT_DEFAULT }),
|
|
503
503
|
r("WORKSPACE_CACHE_SIZE", "orchestration", "string", "k8s 构建缓存卷的大小(PVC 申请量,k8s quantity 形如 20Gi / 500Mi;形不合拒启;只在 WORKSPACE_CACHE=volume 时读)", { staticDefault: WORKSPACE_CACHE_SIZE_DEFAULT }),
|
|
504
504
|
r("WORKSPACE_FILE_MAX_BYTES", "limitsHttp", "number", "已随 workspace 浏览面退役(S-15):值照常校验/落值,应用于空(重启也不生效)", { envTiming: "inert", configKey: "workspaceFileMaxBytes", center: cLimits("workspaceFileMaxBytes", { timing: "inert" }) }),
|
|
505
505
|
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 }),
|
|
506
506
|
r("WORKSPACE_SNAPSHOT_BUCKET", "orchestration", "string", "k8s 工作区快照桶", { derivedDefaultNote: "缺席 ⇒ workspaces" }),
|
|
507
|
-
r("WORKSPACE_SNAPSHOT_EXCLUDE", "orchestration", "csv", "k8s 工作区快照的排除表(相对工作区根的 tar 排除模式,逗号分隔,如 build,.gradle,node_modules/.cache;每项一个 --exclude=./<项>,run 末快照与停驻挂起同一张表 —— 排除的目录恢复后不在,构建产物本就可再生;项形闭:相对路径段,不含 .. / 前导 / / 空白 /
|
|
507
|
+
r("WORKSPACE_SNAPSHOT_EXCLUDE", "orchestration", "csv", "k8s 工作区快照的排除表(相对工作区根的 tar 排除模式,逗号分隔,如 build,.gradle,node_modules/.cache;每项一个 --exclude=./<项>,run 末快照与停驻挂起同一张表 —— 排除的目录恢复后不在,构建产物本就可再生;项形闭:相对路径段,不含 .. / 前导 / / 空白 / 引号,整体通配(只由 * / ? 组成的项,* 会让快照一个顶层项都不剩)也拒,坏项拒启并点名第几项;不读项目 .gitignore)", { derivedDefaultNote: "缺席 = 不排除(上传命令与旧版逐字同)" }),
|
|
508
508
|
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 }),
|
|
509
509
|
r("WORKSPACE_SNAPSHOT_PREFIX", "orchestration", "string", "k8s 工作区快照 key 前缀"),
|
|
510
510
|
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) }),
|
package/dist/config-lkg.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type MigrationReceipt } from "@sema-agent/settings-schema/one-time-migrations";
|
|
2
|
-
import type {
|
|
3
|
-
/** 落盘信封。`effective`/`etag` 逐字=当时的 fetchEffective 返回(JSON verbatim 面)。`formatVersion` 的语义见头注(
|
|
2
|
+
import type { PublishedPromptArtifact } from "@sema-agent/core";
|
|
3
|
+
/** 落盘信封。`effective`/`etag` 逐字=当时的 fetchEffective 返回(JSON verbatim 面)。`formatVersion` 的语义见头注(5 = 载荷的 prompts 是中心层唯一的那种 wire 形)。 */
|
|
4
4
|
export interface PersistedLkg {
|
|
5
|
-
formatVersion:
|
|
5
|
+
formatVersion: 5;
|
|
6
6
|
savedAt: string;
|
|
7
7
|
worker: string;
|
|
8
8
|
/** 拉到这份候选时所用凭证的身份(`center-credential.ts`;摘要形,不含凭证原文)。 */
|
|
@@ -48,10 +48,10 @@ export declare function lkgReadDenyRows(configLkgPath: string | undefined): {
|
|
|
48
48
|
/** 原子落盘一个干净候选(tmp+rename,0600)。BEST-EFFORT:失败=一条 warn 的素材(调用方发),绝不
|
|
49
49
|
* 影响在飞的应用链——LKG 缓存丢失的代价只是下次冷启动回到 env 兜底。 */
|
|
50
50
|
export declare function saveLkg(path: string, worker: string | undefined, identity: string, effective: Record<string, unknown>, etag: string | undefined): Promise<void>;
|
|
51
|
-
/** 一次读回做过的一次性迁移(调用方响亮打一行 `config_lkg_migrated`,并按
|
|
52
|
-
* (2 → 3
|
|
51
|
+
/** 一次读回做过的一次性迁移(调用方响亮打一行 `config_lkg_migrated`,并按 5 写回原位):`fromFormat` = 盘上的版本号;`note` = 信封层的说明
|
|
52
|
+
* (2 → 3 那一步 {@link migrateV2Lkg} / 4 → 5 那一步 {@link migrateV4Lkg});`receipts` = 载荷层 settings-schema 迁移的收据(只点名坐标与处置,不带值)。 */
|
|
53
53
|
export interface LkgReadMigration {
|
|
54
|
-
readonly fromFormat: 2 | 3 | 4;
|
|
54
|
+
readonly fromFormat: 2 | 3 | 4 | 5;
|
|
55
55
|
readonly note?: string;
|
|
56
56
|
readonly receipts: readonly MigrationReceipt[];
|
|
57
57
|
}
|
|
@@ -59,12 +59,12 @@ export interface LkgReadMigration {
|
|
|
59
59
|
* 读盘上 LKG。返回 undefined 的所有情形都「安静地回 env 兜底」(调用方 warn 点名 reason):
|
|
60
60
|
* 文件缺席/JSON 坏/信封形不对/worker 或凭证身份不匹配(防同名文件跨 worker / 跨账号串包;`CONFIG_LKG_PATH`
|
|
61
61
|
* 单一路径时这是唯一的一道)/载荷有迁不动的旧形({@link migrateLkgPayload})/prompts 面复判失败。
|
|
62
|
-
* `migrated`:读回时做过一次性迁移(信封 2 → 3 或载荷的 settings-schema 迁移)—— 调用方响亮打一行,并把交回的
|
|
63
|
-
* `prompts`:候选判官对这份载荷 prompts
|
|
62
|
+
* `migrated`:读回时做过一次性迁移(信封 2 → 3 / 4 → 5 或载荷的 settings-schema 迁移)—— 调用方响亮打一行,并把交回的 5 写回原位。
|
|
63
|
+
* `prompts`:候选判官对这份载荷 prompts 面交出的中心层(引擎 verify 过的发布形 artifact;`undefined` = 载荷不带 prompts 键)—— 调用方采纳直接用它。
|
|
64
64
|
*/
|
|
65
65
|
export declare function loadLkg(path: string, worker: string | undefined, identity: string): Promise<{
|
|
66
66
|
lkg: PersistedLkg;
|
|
67
|
-
prompts:
|
|
67
|
+
prompts: PublishedPromptArtifact | undefined;
|
|
68
68
|
migrated?: LkgReadMigration;
|
|
69
69
|
} | {
|
|
70
70
|
lkg?: undefined;
|
package/dist/config-lkg.js
CHANGED
|
@@ -27,7 +27,7 @@ export function lkgReadDenyRows(configLkgPath) {
|
|
|
27
27
|
return [{ pattern: configLkgPath, caseSensitive: false }];
|
|
28
28
|
}
|
|
29
29
|
export async function saveLkg(path, worker, identity, effective, etag) {
|
|
30
|
-
const body = { formatVersion:
|
|
30
|
+
const body = { formatVersion: 5, savedAt: new Date().toISOString(), worker: worker ?? "global", identity, ...(etag !== undefined ? { etag } : {}), effective };
|
|
31
31
|
const tmp = `${path}.${randomBytes(6).toString("hex")}.tmp`;
|
|
32
32
|
await fs.mkdir(dirname(path), { recursive: true });
|
|
33
33
|
await fs.writeFile(tmp, JSON.stringify(body), { mode: 0o600 });
|
|
@@ -54,7 +54,7 @@ export async function loadLkg(path, worker, identity) {
|
|
|
54
54
|
const formatVersion = p.formatVersion;
|
|
55
55
|
if (formatVersion === 1)
|
|
56
56
|
return { reason: "pre-identity LKG (formatVersion 1) — not read back: it cannot prove whose credential fetched it (S-651); the next clean candidate rewrites it" };
|
|
57
|
-
if (formatVersion !== 2 && formatVersion !== 3 && formatVersion !== 4)
|
|
57
|
+
if (formatVersion !== 2 && formatVersion !== 3 && formatVersion !== 4 && formatVersion !== 5)
|
|
58
58
|
return { reason: `unknown formatVersion ${String(formatVersion)}` };
|
|
59
59
|
if (typeof p.worker !== "string" || p.worker !== (worker ?? "global"))
|
|
60
60
|
return { reason: `worker mismatch (file=${String(p.worker)})` };
|
|
@@ -71,14 +71,20 @@ export async function loadLkg(path, worker, identity) {
|
|
|
71
71
|
envelope = v2.lkg;
|
|
72
72
|
note = v2.migrated;
|
|
73
73
|
}
|
|
74
|
+
if (formatVersion !== 5) {
|
|
75
|
+
const v4 = migrateV4Lkg(envelope, formatVersion);
|
|
76
|
+
if (v4.lkg === undefined)
|
|
77
|
+
return v4;
|
|
78
|
+
note = note === undefined ? v4.migrated : `${note}; ${v4.migrated}`;
|
|
79
|
+
}
|
|
74
80
|
const payload = migrateLkgPayload(envelope.effective);
|
|
75
81
|
if ("refused" in payload)
|
|
76
82
|
return { reason: payload.refused };
|
|
77
83
|
const judged = lkgPayloadJudged(payload.effective, envelope.etag);
|
|
78
84
|
if ("problem" in judged)
|
|
79
85
|
return { reason: judged.problem };
|
|
80
|
-
const lkg = { ...envelope, formatVersion:
|
|
81
|
-
const migrated = formatVersion !==
|
|
86
|
+
const lkg = { ...envelope, formatVersion: 5, effective: payload.effective };
|
|
87
|
+
const migrated = formatVersion !== 5 || payload.receipts.length > 0;
|
|
82
88
|
return migrated ? { lkg, prompts: judged.prompts, migrated: { fromFormat: formatVersion, ...(note !== undefined ? { note } : {}), receipts: payload.receipts } } : { lkg, prompts: judged.prompts };
|
|
83
89
|
}
|
|
84
90
|
export function migrateLkgPayload(effective) {
|
|
@@ -93,6 +99,16 @@ export function migrateLkgPayload(effective) {
|
|
|
93
99
|
}
|
|
94
100
|
return { effective: m.effective, receipts: m.receipts };
|
|
95
101
|
}
|
|
102
|
+
function migrateV4Lkg(lkg, fromFormat) {
|
|
103
|
+
if (Object.hasOwn(lkg.effective, "prompts")) {
|
|
104
|
+
return {
|
|
105
|
+
reason: `formatVersion ${fromFormat} LKG carries a prompts face` +
|
|
106
|
+
" — written before 7.132.0, so it is the retired two-axis wire (declarations / v1 catalog) the engine no longer reads; not read back: " +
|
|
107
|
+
"the center's next candidate (republished as {schemaVersion: 2, artifact}) rewrites it",
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return { lkg, migrated: `formatVersion ${fromFormat} → 5 (one-time): the payload carries no prompts face, read back unchanged` };
|
|
111
|
+
}
|
|
96
112
|
const RETIRED_CATALOG_COORDINATE = /^models\.(0|[1-9][0-9]*)$/;
|
|
97
113
|
function migrateDroppedIdentityRow(row) {
|
|
98
114
|
if (row === null || typeof row !== "object")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DroppedConfigEntry, type RetiredDomainFinding, type UnreadConfigFile } from "./web-admin-client/read-warnings.js";
|
|
1
|
+
import { type DroppedConfigEntry, type RetiredDomainFinding, type UnreadConfigFile, type UnreadConfigKey } 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";
|
|
@@ -28,6 +28,7 @@ import type { ConfigProviderWord } from "./config-types.js";
|
|
|
28
28
|
/** `retiredDomains`(S-1456):带事实的退役域文档(契约包的墓碑)—— 读腿不抛,交成发现,候选判官以成因 `retired_domain` 整拒这份候选(与域判形失败
|
|
29
29
|
* 同一条回落链、同一行拒判);缺席 = 没有。远端腿:那一键不进 effective、其余域照读;本地腿:契约读腿在读便携域之前就拒,交出的候选只有版本
|
|
30
30
|
* (这棵树的内容版本,哈希含退役文件 ⇒ 改 / 删它版本即变),内容是空的 effective(被整拒,不会被应用)。 */
|
|
31
|
+
/** `unreadKeys`:本地读腿读了那份文件、却结构上不读其中一键(`prompts.json` 的 `workers`)—— 同 `unreadFiles`,不进候选门,调用方一键一行 `config_unread_key`。 */
|
|
31
32
|
export type FetchEffectiveResult = {
|
|
32
33
|
effective: EffectiveConfig;
|
|
33
34
|
etag?: string;
|
|
@@ -37,6 +38,7 @@ export type FetchEffectiveResult = {
|
|
|
37
38
|
}>;
|
|
38
39
|
droppedEntries?: DroppedConfigEntry[];
|
|
39
40
|
unreadFiles?: UnreadConfigFile[];
|
|
41
|
+
unreadKeys?: UnreadConfigKey[];
|
|
40
42
|
retiredDomains?: RetiredDomainFinding[];
|
|
41
43
|
readWarnings: readonly EffectiveReadWarning[];
|
|
42
44
|
credentialIdentity?: string;
|
package/dist/config-provider.js
CHANGED
|
@@ -2,7 +2,7 @@ import { readMcpSourceLabel } from "./mcp-source-label.js";
|
|
|
2
2
|
import { createHmac, randomBytes } from "node:crypto";
|
|
3
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, emptyEffective, findSkillContent, renderRefIssue, skillContentHash, } from "@sema-agent/settings-schema";
|
|
5
|
+
import { danglingRefs, emptyEffective, findSkillContent, promptArtifactFor, 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";
|
|
@@ -120,6 +120,7 @@ export class LocalConfigProvider {
|
|
|
120
120
|
const droppedEntries = folded.droppedEntries.map(redactDroppedEntry);
|
|
121
121
|
const errors = [...domainErrors.map((de) => ({ domain: de.domain, error: redactConfigError(de.error) })), ...parseErrors, ...refErrors];
|
|
122
122
|
this.#servedSkills = eff.skills;
|
|
123
|
+
const unreadKeys = localUnreadPromptKeys(eff.prompts);
|
|
123
124
|
return {
|
|
124
125
|
effective: withDroppedCatalogEntries(mapToServiceEffective(eff, eff.version), folded.droppedCatalogEntries),
|
|
125
126
|
etag: tag,
|
|
@@ -127,6 +128,7 @@ export class LocalConfigProvider {
|
|
|
127
128
|
...(errors.length > 0 ? { domainErrors: errors } : {}),
|
|
128
129
|
...(droppedEntries.length > 0 ? { droppedEntries } : {}),
|
|
129
130
|
...(folded.unreadFiles.length > 0 ? { unreadFiles: folded.unreadFiles } : {}),
|
|
131
|
+
...(unreadKeys.length > 0 ? { unreadKeys } : {}),
|
|
130
132
|
...(retired !== undefined ? { retiredDomains: [retired] } : {}),
|
|
131
133
|
};
|
|
132
134
|
}
|
|
@@ -134,6 +136,14 @@ export class LocalConfigProvider {
|
|
|
134
136
|
return findSkillContent(this.#servedSkills, contentHash);
|
|
135
137
|
}
|
|
136
138
|
}
|
|
139
|
+
function localUnreadPromptKeys(prompts) {
|
|
140
|
+
const names = prompts?.workers === undefined ? [] : Object.keys(prompts.workers);
|
|
141
|
+
return names.length === 0 ? [] : [{ file: "prompts.json", domain: "prompts", key: "workers", names }];
|
|
142
|
+
}
|
|
143
|
+
function localPromptsWire(prompts, version) {
|
|
144
|
+
const artifact = prompts === undefined ? undefined : promptArtifactFor(prompts, null);
|
|
145
|
+
return artifact === undefined ? {} : { prompts: { schemaVersion: 2, artifact: { ...artifact, sourceRevision: `local:r${version}` } } };
|
|
146
|
+
}
|
|
137
147
|
export function mapToServiceEffective(eff, version) {
|
|
138
148
|
return {
|
|
139
149
|
version,
|
|
@@ -216,9 +226,7 @@ export function mapToServiceEffective(eff, version) {
|
|
|
216
226
|
};
|
|
217
227
|
}),
|
|
218
228
|
},
|
|
219
|
-
...(eff.prompts
|
|
220
|
-
? { prompts: { schemaVersion: 1, catalog: eff.prompts.catalog } }
|
|
221
|
-
: {}),
|
|
229
|
+
...localPromptsWire(eff.prompts, version),
|
|
222
230
|
scenarios: {
|
|
223
231
|
scenarios: (eff.scenarios.scenarios ?? []).map((sc) => ({
|
|
224
232
|
name: sc.name,
|
package/dist/config-types.d.ts
CHANGED
|
@@ -1107,9 +1107,9 @@ export interface ServiceConfigFlat {
|
|
|
1107
1107
|
keyPrefix?: string;
|
|
1108
1108
|
presignTtlSec?: number;
|
|
1109
1109
|
};
|
|
1110
|
-
/** (a)(clay 拍 a+c,2026-07-27)SQL 默认店的 per-blob 帽显式覆写(字节)。未设 ⇒
|
|
1111
|
-
* 的方言默认(
|
|
1112
|
-
*
|
|
1110
|
+
/** (a)(clay 拍 a+c,2026-07-27)SQL 默认店的 per-blob 帽显式覆写(字节)。未设 ⇒ `sqlBlobDefaultCapBytes`
|
|
1111
|
+
* 的方言默认(MySQL 协议 = 库报的单行上限与包墙 `max_allowed_packet` ÷ 2 取小;事实还没建立 6MiB = TiDB 默认 txn-entry-size-limit;
|
|
1112
|
+
* pg=不设帽);设了 ⇒ 两方言都生效(调高过 entry/packet 限的部署放宽用)。软旋钮:坏值=undefined 走默认。 */
|
|
1113
1113
|
snapshotBlobSqlMaxBytes?: number;
|
|
1114
1114
|
/** (c) 的显式逃生口:云形(mysql|pg 后端)缺 MinIO 本应 boot fail-loud(bytes-in-DB 撞包墙已两役
|
|
1115
1115
|
* 实证,大字节归对象存储);`SNAPSHOT_BLOB_ALLOW_SQL_BYTES=true` 显式接受 SQL 店 + (a) 的帽
|
|
@@ -1526,14 +1526,12 @@ export interface ServiceConfigFlat {
|
|
|
1526
1526
|
* tools for a declared `plan` itself, and no plan entry clamps the hands (only `AUTONOMY=read-only` does). */
|
|
1527
1527
|
planModeEnabled: boolean;
|
|
1528
1528
|
/**
|
|
1529
|
-
*
|
|
1530
|
-
*
|
|
1529
|
+
* `HOOKS_TIMEOUT_MS` —— 请求 `settings.hooks` 那张 mods 注册(`settings.hooks`)每个 handler 的时间预算(ms;一个事件跑一遍本请求的钩子条目)。
|
|
1530
|
+
* **缺席 = 不铸键**;唯一读法 = `hooks/hook-runner.ts` 的 `settingsHooksBudgetMs`(未设 ⇒ 600000,本服务跑钩子子进程的界)。
|
|
1531
1531
|
*
|
|
1532
|
-
* 🔴 `0` 是有效值(
|
|
1532
|
+
* 🔴 `0` 是有效值(引擎按字面:零预算,下一个定时器拍就到期),不是「未设」;
|
|
1533
1533
|
* 坏值(非整数 / 负 / 超 `setTimeout` 32 位上限)**拒启**,解析见 config.ts `parseHooksTimeoutEnv`。
|
|
1534
|
-
*
|
|
1535
|
-
* merge-rescan 745 补折:该腿今日仅同步计数器席位、折上为防倒退)。server 车道一处施加两条腿同时
|
|
1536
|
-
* 生效:既是 `RunnerDeps.hooks`,又是 `resolve-spec` 折进 task hooks 的部署基线。
|
|
1534
|
+
* 部署座的两张观察注册(拒绝计量 / 工具追踪)不读它(同步返回,用引擎缺省)。
|
|
1537
1535
|
*/
|
|
1538
1536
|
hooksTimeoutMs?: number;
|
|
1539
1537
|
/** SVC-2 (adversarial-review): the workflow_journal GC retention — the reaper purges journal rows older than
|
package/dist/config.js
CHANGED
|
@@ -3,7 +3,7 @@ import { DEFAULT_AT_MENTION, DEFAULT_MODEL_REF, mintCapabilityKeys } from "./mod
|
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { join, posix as posixPath } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { compileAllowList, 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";
|
|
6
|
+
import { compileAllowList, inheritEnvPolicyProblem, 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";
|
|
8
8
|
import { parseApprovalHmacKeys, parsePrincipalJwks } from "./auth-keys.js";
|
|
9
9
|
import { DEFAULT_ELICITATION_THROTTLE } from "./elicitation.js";
|
|
@@ -29,7 +29,7 @@ import { lkgPathOverrideOf } from "./config-lkg.js";
|
|
|
29
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
30
|
import { laneLivenessOf } from "./exec-bounds.js";
|
|
31
31
|
import { SANDBOX_IPV6_DEFAULT, SANDBOX_IPV6_WORDS } from "./sandbox-egress-policy.js";
|
|
32
|
-
import { WORKSPACE_CACHE_DEFAULT, WORKSPACE_CACHE_MOUNT_DEFAULT, WORKSPACE_CACHE_SIZE_DEFAULT, WORKSPACE_CACHE_WORDS, isK8sQuantity, mountsOverlap } from "./workspace-cache.js";
|
|
32
|
+
import { WORKSPACE_CACHE_DEFAULT, WORKSPACE_CACHE_MOUNT_DEFAULT, WORKSPACE_CACHE_MOUNT_RESERVED, WORKSPACE_CACHE_SIZE_DEFAULT, WORKSPACE_CACHE_WORDS, isK8sQuantity, mountsOverlap, reservedMountCollision } from "./workspace-cache.js";
|
|
33
33
|
import { REMOTE_EXEC_PROVIDER_WORDS, executionLaneOf, executionLaneRequiredRefusal, isSingleMachineDefaultLane, laneRequiredEnv } from "./execution-lane-caps.js";
|
|
34
34
|
import { MEMORY_ENGINE_BACKENDS, SESSION_BACKENDS, STORE_BACKENDS } from "@sema-agent/settings-schema/execution-lanes";
|
|
35
35
|
import { AUTONOMY_MODES } from "./runtime-governance.js";
|
|
@@ -467,6 +467,12 @@ function parseNameListEnv(name, raw, opts) {
|
|
|
467
467
|
}
|
|
468
468
|
const ENV_VAR_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
469
469
|
const ENV_NAME_ALLOWLIST_WITHHELD = "<withheld: entries are not echoed — a value pasted in place of a name can pass the name check>";
|
|
470
|
+
function ownCredentialPutBackProblem(name) {
|
|
471
|
+
const engine = inheritEnvPolicyProblem([name]);
|
|
472
|
+
return engine === undefined
|
|
473
|
+
? undefined
|
|
474
|
+
: `this deployment's own credential — a put-back list hands the named variable back, as written, to the child the engine withheld it from (the engine refuses it on any allow list: ${engine})`;
|
|
475
|
+
}
|
|
470
476
|
export function parseEnvNameAllowlist(knob, singleUserTurnkey) {
|
|
471
477
|
const raw = process.env[knob];
|
|
472
478
|
if (raw === undefined || raw === "")
|
|
@@ -480,7 +486,9 @@ export function parseEnvNameAllowlist(knob, singleUserTurnkey) {
|
|
|
480
486
|
? 'not an environment-variable name (letters, digits and "_", not starting with a digit)'
|
|
481
487
|
: ENV_NAME_ALLOWLIST_KNOB_NAMES.has(seg.toUpperCase())
|
|
482
488
|
? `the name of a name-list knob (${[...ENV_NAME_ALLOWLIST_KNOB_NAMES].join(" / ")}: their raw text is withheld from every child process and sandbox; naming one would put that text back)`
|
|
483
|
-
:
|
|
489
|
+
: spec.channel === "host-put-back"
|
|
490
|
+
? ownCredentialPutBackProblem(seg)
|
|
491
|
+
: undefined;
|
|
484
492
|
if (problem === undefined)
|
|
485
493
|
return;
|
|
486
494
|
throw new Error(`env ${knob}: entry #${i + 1} of ${segments.length} is ${problem}` +
|
|
@@ -684,7 +692,7 @@ function parseHooksTimeoutEnv() {
|
|
|
684
692
|
return undefined;
|
|
685
693
|
const n = parseNumOrFail("HOOKS_TIMEOUT_MS", raw);
|
|
686
694
|
if (!Number.isInteger(n) || n < 0 || n > 2147483647) {
|
|
687
|
-
throw new Error(`env HOOKS_TIMEOUT_MS="${raw}" must be an integer in [0, 2147483647] ms (0 = every hook
|
|
695
|
+
throw new Error(`env HOOKS_TIMEOUT_MS="${raw}" must be an integer in [0, 2147483647] ms (0 = a zero budget for every request-hook handler; unset = 600000)`);
|
|
688
696
|
}
|
|
689
697
|
return n;
|
|
690
698
|
}
|
|
@@ -2461,6 +2469,11 @@ function k8sWorkspaceCache() {
|
|
|
2461
2469
|
throw new Error(`env WORKSPACE_CACHE_MOUNT=${mount} overlaps the workspace mount ${workspace} (K8S_MOUNT_PATH) — the cache volume must sit OUTSIDE the workspace ` +
|
|
2462
2470
|
"(the workspace is snapshotted between runs, the cache is not); pick a separate absolute path such as /cache");
|
|
2463
2471
|
}
|
|
2472
|
+
const reserved = reservedMountCollision(mount);
|
|
2473
|
+
if (reserved !== undefined) {
|
|
2474
|
+
throw new Error(`env WORKSPACE_CACHE_MOUNT=${mount} collides with the reserved image directory ${reserved} (a volume at, under or above it hides what the sandbox image keeps there) — ` +
|
|
2475
|
+
`pick a separate absolute path such as /cache; reserved: ${WORKSPACE_CACHE_MOUNT_RESERVED.join(" ")}`);
|
|
2476
|
+
}
|
|
2464
2477
|
return { mount, size };
|
|
2465
2478
|
}
|
|
2466
2479
|
export function loadConfig() {
|
|
@@ -62,7 +62,7 @@ export declare function asInstructionKind(v: string): DeviceInstructionKind | nu
|
|
|
62
62
|
* 结果帧的错误码闭集 = core 的 `FileErrorCode ∪ ExecutionErrorCode`(§5.1「error code 全闭集」:
|
|
63
63
|
* 未知值映射为协议错误而非透传 string)。`satisfies` 保证这里没有 core 不认识的词。
|
|
64
64
|
*/
|
|
65
|
-
export declare const DEVICE_OUTCOME_ERROR_CODES: readonly ["aborted", "already_exists", "auth_failed", "callback_error", "invalid", "is_directory", "not_directory", "not_found", "not_supported", "outcome_unknown", "permission_denied", "precondition_failed", "shell_unavailable", "spawn_error", "suspended", "target_unavailable", "timeout", "transport_lost", "unknown"];
|
|
65
|
+
export declare const DEVICE_OUTCOME_ERROR_CODES: readonly ["aborted", "already_exists", "auth_failed", "callback_error", "invalid", "is_directory", "liveness_no_output", "not_directory", "not_found", "not_supported", "outcome_unknown", "permission_denied", "precondition_failed", "shell_unavailable", "spawn_error", "suspended", "target_unavailable", "timeout", "transport_lost", "unknown"];
|
|
66
66
|
export type DeviceOutcomeErrorCode = (typeof DEVICE_OUTCOME_ERROR_CODES)[number];
|
|
67
67
|
/**
|
|
68
68
|
* **编译期**对账的另一半:core 往 `FileErrorCode`/`ExecutionErrorCode` 加一个词而本表没跟 ⇒ `Exclude`
|
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
* 带外凭据(e2b / docker / k8s 车道本来就是多租户 fleet 的主形),与 LSP 那条「本机子进程」的形不同;多租户下起服说一句。
|
|
11
11
|
* · `BAKE_ENV_ALLOW`(S-684 残余,7.103.0)由 **bake-runner 进程**读(构建宿主守护进程:没有主体、没有租户 ⇒ 没有姿态列,
|
|
12
12
|
* 不进 {@link describeAllowlistPostures} 的姿态句)。它与服务侧四只旋钮同一只解析器、同一只「点名放行」谓词、同一条「原文按凭据类」律。
|
|
13
|
+
* · `channel` = 这张名单**交给谁、在谁的减法之上**(闭集两词,解析器按它定「不许点哪些名」):
|
|
14
|
+
* - `host-put-back`(`LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW`)—— 剥后放回形:宿主子进程的 env 先经唯一组合(引擎扣掉本服务自有凭据 + 形状剥),
|
|
15
|
+
* 名单点到的键再从本进程环境**原样**取回叠上去。点到本服务自有凭据名 = 把引擎刚扣下的那枚交回去 ⇒ 起服拒,判官 = 引擎同一只
|
|
16
|
+
* (`inheritEnvPolicyProblem`,读起服声明;与引擎拒嵌入方白名单同句)。
|
|
17
|
+
* - `sandbox-grant`(三只沙箱名单)—— 沙箱 env 的唯一来源(沙箱不从本进程继承任何东西),部署方显式交出的带外凭据(S-715 照转发);
|
|
18
|
+
* 本列不在「自有凭据」律的射程里,只拒点名名单型旋钮(原文按凭据类)。
|
|
13
19
|
* 表是 `Record<旋钮, …>`:闭集加一只旋钮而不补行 = 编译红;行形随读它的进程定(服务进程 ⇒ 必须写姿态列)。
|
|
14
20
|
*
|
|
15
21
|
* 🔴 **姿态列只在这里写一次**([ref];7.101.0 合并复审 O9):凡要对人说「多租户下哪只旋钮忽略、哪只照转发」的句子,一律取
|
|
@@ -28,14 +34,18 @@ export type EnvNameAllowlistPosture = {
|
|
|
28
34
|
readonly kind: "ignored";
|
|
29
35
|
readonly why: string;
|
|
30
36
|
};
|
|
31
|
-
/**
|
|
37
|
+
/** 名单交给谁、在谁的减法之上(闭集;规则见表头注 `channel` 一条)。 */
|
|
38
|
+
export type EnvNameAllowlistChannel = "host-put-back" | "sandbox-grant";
|
|
39
|
+
/** 服务侧旋钮一行:拒句示例 + 交付形 + 多租户姿态。 */
|
|
32
40
|
export interface ServerEnvNameAllowlistKnobRow {
|
|
33
41
|
readonly example: string;
|
|
42
|
+
readonly channel: EnvNameAllowlistChannel;
|
|
34
43
|
readonly multiTenant: EnvNameAllowlistPosture;
|
|
35
44
|
}
|
|
36
|
-
/** runner
|
|
45
|
+
/** runner 旋钮一行:拒句示例 + 交付形(没有姿态可言)。 */
|
|
37
46
|
export interface RunnerEnvNameAllowlistKnobRow {
|
|
38
47
|
readonly example: string;
|
|
48
|
+
readonly channel: EnvNameAllowlistChannel;
|
|
39
49
|
}
|
|
40
50
|
export type EnvNameAllowlistKnobTable = {
|
|
41
51
|
readonly [K in EnvNameAllowlistKnob]: K extends ServerEnvNameAllowlistKnob ? ServerEnvNameAllowlistKnobRow : RunnerEnvNameAllowlistKnobRow;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
export const ENV_NAME_ALLOWLIST_KNOBS = {
|
|
2
2
|
LSP_ENV_ALLOW: {
|
|
3
3
|
example: "LSP_ENV_ALLOW=NPM_TOKEN,CARGO_REGISTRIES_MY_REG_TOKEN",
|
|
4
|
+
channel: "host-put-back",
|
|
4
5
|
multiTenant: { kind: "ignored", why: "the host-lane language server is not started in this posture, and the language-server env keeps the full secret strip" },
|
|
5
6
|
},
|
|
6
|
-
E2B_SANDBOX_ENV: { example: "E2B_SANDBOX_ENV=GIT_TOKEN,NPM_TOKEN", multiTenant: { kind: "honored" } },
|
|
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" } },
|
|
9
|
-
BAKE_ENV_ALLOW: { example: "BAKE_ENV_ALLOW=REGISTRY_PASSWORD,NPM_TOKEN" },
|
|
7
|
+
E2B_SANDBOX_ENV: { example: "E2B_SANDBOX_ENV=GIT_TOKEN,NPM_TOKEN", channel: "sandbox-grant", multiTenant: { kind: "honored" } },
|
|
8
|
+
DOCKER_SANDBOX_ENV: { example: "DOCKER_SANDBOX_ENV=GIT_TOKEN,NPM_TOKEN", channel: "sandbox-grant", multiTenant: { kind: "honored" } },
|
|
9
|
+
K8S_SANDBOX_ENV: { example: "K8S_SANDBOX_ENV=GIT_TOKEN,NPM_TOKEN", channel: "sandbox-grant", multiTenant: { kind: "honored" } },
|
|
10
|
+
BAKE_ENV_ALLOW: { example: "BAKE_ENV_ALLOW=REGISTRY_PASSWORD,NPM_TOKEN", channel: "host-put-back" },
|
|
10
11
|
};
|
|
11
12
|
export const ENV_NAME_ALLOWLIST_KNOB_NAMES = new Set(Object.keys(ENV_NAME_ALLOWLIST_KNOBS));
|
|
12
13
|
const POSTURE_PHRASE = {
|
package/dist/exec-bounds.d.ts
CHANGED
|
@@ -12,8 +12,10 @@
|
|
|
12
12
|
* 是它报的那一界。
|
|
13
13
|
*
|
|
14
14
|
* 与 core 远端契约(`ExecStreamOptions.readTimeoutMs`:「缺省也 SHOULD 有活性界,一条命令不得等到环境死」)的对齐:
|
|
15
|
-
* 说了墙钟的命令被墙钟兜住,不会无限等;两界都没说的命令,在有活性界的车道(k8s / e2b)
|
|
16
|
-
*
|
|
15
|
+
* 说了墙钟的命令被墙钟兜住,不会无限等;两界都没说的命令,在有活性界的车道(k8s / e2b)上仍由它兜底。**切断码按触发的那一界**(core 7.52.0 #1795:
|
|
16
|
+
* 两套执行码闭集各有一词):墙钟 ⇒ `timeout`;静默界(调用方的 `readTimeoutMs` 或车道活性界)⇒ `liveness_no_output`,带窗口秒数 `noOutputSec`(车道的界 /
|
|
17
|
+
* 调用方说的静默界,从不是请求的预算)—— 两者解释自己用的是两个数,消费方(core 的 Bash 工具:「no output for N s」对「timed out after N s」)按码分。
|
|
18
|
+
* 静默切断的码、句、秒数只在 {@link buildLivenessCut} 一处铸,六车道同读。
|
|
17
19
|
*
|
|
18
20
|
* 不在本律里的界(adapter 自己的上限,不是调用方说的话,不关活性界):k8s 文件读写的数据上限 `dataTimeoutMs`、e2b 交给
|
|
19
21
|
* 供应商的沙箱寿命上限。adapter 自己的整段数据搬运(k8s 快照 tar 上 / 下)天生静默,它们**自己说**一个墙钟(数据上限),
|
|
@@ -64,6 +66,16 @@ export declare function firstBoundOf(bounds: CommandBounds): {
|
|
|
64
66
|
readonly ms: number;
|
|
65
67
|
readonly cut: "wall" | LivenessBound;
|
|
66
68
|
} | undefined;
|
|
67
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* 🔴 **一次静默切断 —— 唯一铸点**(六条车道 host / e2b / k8s / ssh / adb / local-docker 同读;纯数据,车道用它构造自己那一型的错误):
|
|
71
|
+
* 码恒为 `liveness_no_output`(core 7.52.0 #1795;墙钟切断照旧 `timeout`,不经本函数),句子 = {@link livenessCutMessage},`noOutputSec` = 静默窗口的整秒数
|
|
72
|
+
* (core `ExecutionError` 第五构造参;core 读它时向下取整、不足 1 秒不说 —— 本函数同读:不足 1 秒的窗口不带这一位)。远端流式错误(`RemoteExecutionError`)没有这一位的座,只带码与句。
|
|
73
|
+
*/
|
|
74
|
+
export declare function buildLivenessCut(bound: LivenessBound): {
|
|
75
|
+
readonly code: "liveness_no_output";
|
|
76
|
+
readonly message: string;
|
|
77
|
+
readonly noOutputSec?: number;
|
|
78
|
+
};
|
|
79
|
+
/** 活性切断的句子 —— {@link buildLivenessCut} 的句子半(车道兜底的界点名旋钮与出路;调用方自己说的界点名那一参数)。车道不直调它:码与句一处铸。 */
|
|
68
80
|
export declare function livenessCutMessage(bound: LivenessBound): string;
|
|
69
81
|
//# sourceMappingURL=exec-bounds.d.ts.map
|
package/dist/exec-bounds.js
CHANGED
|
@@ -26,6 +26,10 @@ function spoken(ms) {
|
|
|
26
26
|
return `${ms} ms`;
|
|
27
27
|
return ms % 1000 === 0 ? `${ms / 1000} s` : `${(ms / 1000).toFixed(1)} s`;
|
|
28
28
|
}
|
|
29
|
+
export function buildLivenessCut(bound) {
|
|
30
|
+
const sec = Math.floor(bound.ms / 1000);
|
|
31
|
+
return { code: "liveness_no_output", message: livenessCutMessage(bound), ...(sec >= 1 ? { noOutputSec: sec } : {}) };
|
|
32
|
+
}
|
|
29
33
|
export function livenessCutMessage(bound) {
|
|
30
34
|
switch (bound.setBy) {
|
|
31
35
|
case "lane":
|
|
@@ -58,8 +58,8 @@ export interface ExecutionLaneCaps {
|
|
|
58
58
|
* `lane === undefined || lane === "host"` 的同义形,分叉过就是记忆边界判错盘)。读本位的真装配点:
|
|
59
59
|
* `boot/deferred-sandbox-path-env.ts` 的 `isSandboxPathAdjudicationLane`(resolve-spec 写门 / parked 赎回腿 /
|
|
60
60
|
* 执行环境装配三处的唯一属主)、`memory-scope.ts` 的 `memoryEngineRemoteLanePosture`、
|
|
61
|
-
* `boot/memory-boundary.ts` 的 `buildMemoryBoundaryLaneFacts`(stores)
|
|
62
|
-
* `
|
|
61
|
+
* `boot/memory-boundary.ts` 的 `buildMemoryBoundaryLaneFacts`(stores)。(「本会话没有持久记忆」的披露归引擎判、引擎渲染 ——
|
|
62
|
+
* 目录条目 `core/memory.no-persistent-store`,本仓只交 spec 上的事实,不再读本位做判别。)⚠️ `in-process` 在本位上是 YES(hooks/进程内读确实在本机盘上),
|
|
63
63
|
* 但它**没有手** —— 问「手在不在本机盘上」要读 {@link handsOnWorkerFilePlane},不是只读本位。 */
|
|
64
64
|
readonly hostFilePlane: LaneCapability;
|
|
65
65
|
/** core 的 `isRemoteExecutionEnv` 对本车道的判决(鸭子类型,**含 host**)= core 拿没拿到执行环境 = 手带挂没挂。
|
|
@@ -297,4 +297,11 @@ export interface LaneHomeDeployment {
|
|
|
297
297
|
* 认不出的车道 ⇒ `undefined`(调用方 fail-closed)。生产链上不可达:`loadConfig` 的 [ref] 拒启门先咬。
|
|
298
298
|
*/
|
|
299
299
|
export declare function executionLaneHomeDir(deployment: LaneHomeDeployment): string | undefined;
|
|
300
|
+
/**
|
|
301
|
+
* 「这条部署的执行车道**有手**、而家目录答不出」时起服那一行的 `note`(纯字符串 ⇒ `build*`);否则 `undefined`(不出这一行)。
|
|
302
|
+
* 判据只读 {@link executionLaneHomeDir}(家目录的唯一属主)与能力表 `coreRemoteExecutionEnv` 位(有没有手):不另写车道清单。
|
|
303
|
+
* 代价如实:引擎 7.52.0 起家锚拒读行放不下 ⇒ 每一次泄内容的递归读在全 shell 面强制问人(allow / 模式 / bypass 都放不掉)、只读面拒;`~/` 形规则在下单时
|
|
304
|
+
* 就被 422 拒。出路只有一条:声明执行环境的家目录(`$HOME` 读出来的那个绝对路径)。这句话陈述的是事实,不是告警 —— 要它消失就声明家目录。
|
|
305
|
+
*/
|
|
306
|
+
export declare function buildUndeclaredHomeNote(deployment: LaneHomeDeployment): string | undefined;
|
|
300
307
|
//# sourceMappingURL=execution-lane-caps.d.ts.map
|
|
@@ -261,4 +261,15 @@ export function executionLaneHomeDir(deployment) {
|
|
|
261
261
|
return undefined;
|
|
262
262
|
}
|
|
263
263
|
}
|
|
264
|
+
export function buildUndeclaredHomeNote(deployment) {
|
|
265
|
+
if (executionLaneHomeDir(deployment) !== undefined)
|
|
266
|
+
return undefined;
|
|
267
|
+
const lane = executionLaneOf(deployment.remoteExec?.provider);
|
|
268
|
+
if (lane === undefined || executionLaneCaps(lane).coreRemoteExecutionEnv !== "supported")
|
|
269
|
+
return undefined;
|
|
270
|
+
return (`the ${lane} lane declares no home for its execution environment (REMOTE_EXEC_HOME_DIR is unset, and on this lane the home belongs to the image / target user): ` +
|
|
271
|
+
`the engine cannot place its home-anchored read-deny rows, so every contents-disclosing recursive read (grep -r, rg, git grep, tar c, …) asks a person on the full shell — ` +
|
|
272
|
+
`no allow rule, mode or bypass releases that question — and is refused on the read-only face, so unattended tasks cannot search code; "~/" permission rules are refused at submission. ` +
|
|
273
|
+
`Declare the home: REMOTE_EXEC_HOME_DIR=<the absolute path the environment's $HOME reads>`);
|
|
274
|
+
}
|
|
264
275
|
//# sourceMappingURL=execution-lane-caps.js.map
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 引擎的 `classic.*` 站 —— 本仓挂 handler 的唯一入口(core 7.52.0 起扩展点 = mods 注册,`Hooks` 记录退役)。
|
|
3
|
+
*
|
|
4
|
+
* 两件事只写在这里:
|
|
5
|
+
* ① **事件名 → { `e` 型, 答案型 }**:core 逐个导出了每站的 `e` 型与答案型,但没有导出二者的映射(宿主侧配对是今天的唯一读法)。
|
|
6
|
+
* 这张对位表是那一配对的唯一一份;core 导出映射型的那一版,本表改读它、删掉手写的十一行。
|
|
7
|
+
* ② **handler 怎么挂**:链成员「无意见 ⇒ `next(e)`」(链 handler 返回 `undefined` 是站点违约,refuse 站上即 fail-closed 拒),
|
|
8
|
+
* 观察者「恒返回 `undefined`」(观察者的判词不采纳、被引擎报告)。两条都在 {@link hangClassic} / {@link observeClassic} 里成形,
|
|
9
|
+
* 调用方只写「这一站我答什么」或「这一站我看什么」,不再各自记得这两条。
|
|
10
|
+
*
|
|
11
|
+
* 站的集合 = 引擎事件表里有站的 `classic.*` 名(一条钉从 `MOD_EVENT_TABLE` 派生对拍,不手抄第二份)。
|
|
12
|
+
* 观察站(`StopFailure` / `PostCompact` / `PermissionDenied`)只许观察者:答案形是「无」,core 的迁移配方要求挂 `{ observe: true }`。
|
|
13
|
+
*/
|
|
14
|
+
import type { EngineDollar, On, PermissionDeniedPayload, PostCompactEvent, PostToolBatchEvent, PostToolBatchResult, PostToolUseEvent, PostToolUseFailureEvent, PostToolUseFailureResult, PostToolUseResult, PreCompactEvent, PreCompactResult, PreToolUseEvent, PreToolUseResult, StopEvent, StopFailureEvent, StopHookResult, UserPromptSubmitEvent, UserPromptSubmitResult } from "@sema-agent/core";
|
|
15
|
+
/** 每一站的 `e` 型与答案型(答案 `void` = 观察站)。 */
|
|
16
|
+
export interface ClassicStationTypes {
|
|
17
|
+
"classic.PreToolUse": {
|
|
18
|
+
e: PreToolUseEvent;
|
|
19
|
+
answer: PreToolUseResult;
|
|
20
|
+
};
|
|
21
|
+
"classic.PostToolUse": {
|
|
22
|
+
e: PostToolUseEvent;
|
|
23
|
+
answer: PostToolUseResult;
|
|
24
|
+
};
|
|
25
|
+
"classic.PostToolUseFailure": {
|
|
26
|
+
e: PostToolUseFailureEvent;
|
|
27
|
+
answer: PostToolUseFailureResult;
|
|
28
|
+
};
|
|
29
|
+
"classic.PostToolBatch": {
|
|
30
|
+
e: PostToolBatchEvent;
|
|
31
|
+
answer: PostToolBatchResult;
|
|
32
|
+
};
|
|
33
|
+
"classic.UserPromptSubmit": {
|
|
34
|
+
e: UserPromptSubmitEvent;
|
|
35
|
+
answer: UserPromptSubmitResult;
|
|
36
|
+
};
|
|
37
|
+
"classic.Stop": {
|
|
38
|
+
e: StopEvent;
|
|
39
|
+
answer: StopHookResult;
|
|
40
|
+
};
|
|
41
|
+
"classic.SubagentStop": {
|
|
42
|
+
e: StopEvent;
|
|
43
|
+
answer: StopHookResult;
|
|
44
|
+
};
|
|
45
|
+
"classic.StopFailure": {
|
|
46
|
+
e: StopFailureEvent;
|
|
47
|
+
answer: void;
|
|
48
|
+
};
|
|
49
|
+
"classic.PreCompact": {
|
|
50
|
+
e: PreCompactEvent;
|
|
51
|
+
answer: PreCompactResult;
|
|
52
|
+
};
|
|
53
|
+
"classic.PostCompact": {
|
|
54
|
+
e: PostCompactEvent;
|
|
55
|
+
answer: void;
|
|
56
|
+
};
|
|
57
|
+
"classic.PermissionDenied": {
|
|
58
|
+
e: PermissionDeniedPayload;
|
|
59
|
+
answer: void;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export type ClassicStation = keyof ClassicStationTypes;
|
|
63
|
+
/** 每一站能挂什么:`chain` = 链成员(会作答)与观察者都可;`observe` = 只许观察者。 */
|
|
64
|
+
export declare const CLASSIC_STATION_ROLE: {
|
|
65
|
+
readonly "classic.PreToolUse": "chain";
|
|
66
|
+
readonly "classic.PostToolUse": "chain";
|
|
67
|
+
readonly "classic.PostToolUseFailure": "chain";
|
|
68
|
+
readonly "classic.PostToolBatch": "chain";
|
|
69
|
+
readonly "classic.UserPromptSubmit": "chain";
|
|
70
|
+
readonly "classic.Stop": "chain";
|
|
71
|
+
readonly "classic.SubagentStop": "chain";
|
|
72
|
+
readonly "classic.StopFailure": "observe";
|
|
73
|
+
readonly "classic.PreCompact": "chain";
|
|
74
|
+
readonly "classic.PostCompact": "observe";
|
|
75
|
+
readonly "classic.PermissionDenied": "observe";
|
|
76
|
+
};
|
|
77
|
+
/** 一站的 handler 体:读 `e`,答这一站的答案;`undefined` = 无意见(链成员由 {@link hangClassic} 交给 `next(e)`)。 */
|
|
78
|
+
export type ClassicAnswer<K extends ClassicStation> = (e: ClassicStationTypes[K]["e"]) => Promise<ClassicStationTypes[K]["answer"] | undefined>;
|
|
79
|
+
/**
|
|
80
|
+
* 按站的角色挂一只 handler:链站 ⇒ 链成员 `(await answer(e)) ?? next(e)`;观察站 ⇒ 观察者(体照跑、恒返回 `undefined`)。
|
|
81
|
+
* `e` 的型由 {@link ClassicStationTypes} 给(引擎交来的是本站的 `e`;配对见头注 ①)。
|
|
82
|
+
*/
|
|
83
|
+
export declare function hangClassic<K extends ClassicStation>(on: On<EngineDollar>, station: K, answer: ClassicAnswer<K>): void;
|
|
84
|
+
/** 挂一只观察者(任何站都可):拿分离副本、不进链、恒返回 `undefined`。 */
|
|
85
|
+
export declare function observeClassic<K extends ClassicStation>(on: On<EngineDollar>, station: K, watch: (e: ClassicStationTypes[K]["e"]) => void | Promise<void>): void;
|
|
86
|
+
//# sourceMappingURL=classic-stations.d.ts.map
|