@sema-agent/server 7.148.0 → 7.149.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 +429 -0
- package/README.md +16 -1
- package/README.zh-CN.md +4 -0
- package/USAGE.md +89 -55
- package/dist/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +32 -32
- package/dist/approval-leg-origin.d.ts +33 -0
- package/dist/approval-leg-origin.js +4 -0
- package/dist/auth-bridge.d.ts +9 -1
- package/dist/auth-bridge.js +4 -4
- package/dist/auth-keys.d.ts +10 -1
- package/dist/auth-keys.js +8 -0
- package/dist/boot/execution-env.js +10 -11
- package/dist/boot/execution-lane.d.ts +6 -4
- package/dist/boot/execution-lane.js +3 -1
- package/dist/boot/org-delivery.d.ts +3 -2
- package/dist/boot/resolve-spec.js +6 -4
- package/dist/boot/runner-deps.js +3 -1
- package/dist/boot/stage-01-config.d.ts +1 -0
- package/dist/boot/stage-01-config.js +4 -3
- package/dist/boot/stage-02-web-admin-pull.d.ts +1 -0
- package/dist/boot/stage-02-web-admin-pull.js +10 -2
- 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 +1 -0
- package/dist/boot/stage-06-runners.d.ts +2 -1
- package/dist/boot/stage-07-capability-layer.d.ts +2 -1
- package/dist/boot/stage-08-reapers.d.ts +2 -1
- package/dist/boot/stage-09-leader.d.ts +2 -1
- package/dist/boot/stage-10-http-server.d.ts +2 -1
- package/dist/boot/stores.d.ts +3 -0
- package/dist/boot/stores.js +22 -19
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/capability-facts.d.ts +5 -4
- package/dist/capability-facts.js +3 -14
- package/dist/card-settle-stored-scope.d.ts +56 -0
- package/dist/card-settle-stored-scope.js +27 -0
- package/dist/card-void.d.ts +7 -12
- package/dist/card-void.js +2 -7
- package/dist/config-catalog.d.ts +12 -0
- package/dist/config-catalog.js +36 -32
- package/dist/config-invariants.d.ts +5 -4
- package/dist/config-invariants.js +4 -4
- package/dist/config-types.d.ts +37 -5
- package/dist/config.d.ts +6 -5
- package/dist/config.js +35 -24
- package/dist/context-window-notice.d.ts +31 -0
- package/dist/context-window-notice.js +28 -0
- package/dist/deployment-shape.d.ts +20 -11
- package/dist/deployment-shape.js +1 -0
- package/dist/env-name-allowlist-knobs.d.ts +6 -5
- package/dist/env-name-allowlist-knobs.js +5 -0
- package/dist/execution-lane-caps.d.ts +20 -5
- package/dist/execution-lane-caps.js +18 -4
- package/dist/hooks/command-spawn.d.ts +7 -2
- package/dist/hooks/command-spawn.js +13 -6
- package/dist/hooks/hook-runner.d.ts +5 -0
- package/dist/hooks/hook-runner.js +11 -7
- package/dist/http/admission.js +3 -3
- package/dist/http/approval-sweeps.js +3 -2
- package/dist/http/claim-heartbeat.d.ts +3 -3
- package/dist/http/claim-heartbeat.js +3 -3
- package/dist/http/claimed-run.d.ts +16 -9
- package/dist/http/claimed-run.js +8 -0
- package/dist/http/dispatch.js +5 -3
- package/dist/http/durable-run-leg.d.ts +8 -1
- package/dist/http/durable-run-leg.js +30 -11
- package/dist/http/execution-context.d.ts +115 -14
- package/dist/http/execution-context.js +130 -40
- package/dist/http/owner-access.d.ts +3 -2
- package/dist/http/owner-access.js +2 -3
- package/dist/http/principal-gate.d.ts +18 -11
- package/dist/http/principal-gate.js +3 -1
- package/dist/http/resume-ctx-read.d.ts +14 -3
- package/dist/http/resume-ctx-read.js +8 -2
- package/dist/http/resume-legs.d.ts +35 -3
- package/dist/http/resume-legs.js +244 -92
- package/dist/http/route-ctx.d.ts +6 -0
- package/dist/http/routes/a2a-serve.js +2 -0
- package/dist/http/routes/approvals-assistant.js +3 -2
- package/dist/http/routes/capabilities.js +1 -1
- package/dist/http/routes/diagnostics.d.ts +3 -1
- package/dist/http/routes/diagnostics.js +30 -5
- package/dist/http/routes/principal-inbox.d.ts +3 -1
- package/dist/http/routes/principal-inbox.js +3 -2
- package/dist/http/routes/runs.js +10 -7
- package/dist/http/routes/session-sync.d.ts +24 -5
- package/dist/http/routes/session-sync.js +46 -34
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/tasks.js +127 -93
- package/dist/http/server.d.ts +4 -5
- package/dist/http/server.js +30 -5
- package/dist/http/submit-ctx.d.ts +1 -0
- package/dist/http/submit-ctx.js +2 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/leg-facts.d.ts +7 -2
- package/dist/leg-facts.js +1 -0
- package/dist/local-store-declaration.d.ts +54 -0
- package/dist/local-store-declaration.js +59 -0
- package/dist/mcp-assertion-header.d.ts +1 -1
- package/dist/mcp-assertion-header.js +1 -1
- package/dist/memory-project-layer.js +1 -1
- package/dist/memory-scope.d.ts +4 -4
- package/dist/memory-scope.js +4 -4
- package/dist/memory-sync-client.js +2 -2
- package/dist/model-context-window.d.ts +50 -11
- package/dist/model-context-window.js +20 -1
- package/dist/model-entry-refusal.d.ts +5 -4
- package/dist/model-entry-refusal.js +17 -3
- package/dist/model-reach-scope.d.ts +2 -1
- package/dist/observability/fail-open.d.ts +14 -2
- package/dist/observability/fail-open.js +14 -2
- package/dist/observability/metrics.js +1 -1
- package/dist/observability/run-terminal.js +1 -0
- package/dist/observability/secret-env-scrub.d.ts +1 -1
- package/dist/observability/secret-env-scrub.js +1 -1
- package/dist/org-delivery-gate.d.ts +31 -6
- package/dist/org-delivery-gate.js +7 -4
- package/dist/owner-faces.d.ts +3 -2
- package/dist/park-row-commit.d.ts +67 -0
- package/dist/park-row-commit.js +76 -0
- package/dist/parked-decide.d.ts +9 -7
- package/dist/parked-decide.js +25 -6
- package/dist/peer-directory.d.ts +1 -1
- package/dist/plugins/adoption-log-sql.d.ts +3 -3
- package/dist/plugins/adoption-log-sql.js +19 -19
- package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
- package/dist/plugins/approval-ask-store-sql.js +3 -5
- package/dist/plugins/approval-exemption-skill-cutoff.d.ts +64 -0
- package/dist/plugins/approval-exemption-skill-cutoff.js +122 -0
- package/dist/plugins/approval-exemption-skill-m46.d.ts +0 -6
- package/dist/plugins/approval-exemption-skill-m46.js +6 -10
- package/dist/plugins/approval-exemption-store.d.ts +26 -1
- package/dist/plugins/approval-exemption-store.js +28 -19
- package/dist/plugins/ensure-schema-lock-policy.d.ts +36 -3
- package/dist/plugins/ensure-schema-lock-policy.js +75 -9
- package/dist/plugins/file-run-store.d.ts +22 -9
- package/dist/plugins/file-run-store.js +50 -22
- package/dist/plugins/local-checkpoint-store.d.ts +4 -0
- package/dist/plugins/local-checkpoint-store.js +2 -1
- package/dist/plugins/local-data-root-admission.d.ts +52 -0
- package/dist/plugins/local-data-root-admission.js +100 -0
- package/dist/plugins/local-engine-high-water.d.ts +28 -7
- package/dist/plugins/local-engine-high-water.js +27 -22
- package/dist/plugins/local-session-store.d.ts +134 -49
- package/dist/plugins/local-session-store.js +149 -108
- package/dist/plugins/memory-run-store.d.ts +14 -9
- package/dist/plugins/memory-run-store.js +47 -21
- package/dist/plugins/one-time-migration-marker.d.ts +19 -3
- package/dist/plugins/one-time-migration-marker.js +7 -1
- package/dist/plugins/one-time-migrations.d.ts +46 -20
- package/dist/plugins/one-time-migrations.js +102 -79
- package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
- package/dist/plugins/org-delivery-quota-store.js +29 -14
- package/dist/plugins/permission-rule-store-sql.d.ts +1 -1
- package/dist/plugins/permission-rule-store-sql.js +5 -9
- package/dist/plugins/pg-pool.d.ts +1 -1
- package/dist/plugins/pg-pool.js +10 -12
- package/dist/plugins/remote-env-device.d.ts +3 -2
- package/dist/plugins/remote-env-e2b.d.ts +1 -7
- package/dist/plugins/remote-env-e2b.js +10 -7
- package/dist/plugins/remote-env-host.d.ts +50 -9
- package/dist/plugins/remote-env-host.js +77 -20
- package/dist/plugins/remote-env-k8s.js +4 -2
- package/dist/plugins/remote-env-local-docker.d.ts +6 -3
- package/dist/plugins/remote-env-local-docker.js +8 -23
- package/dist/plugins/run-store-sql.d.ts +26 -7
- package/dist/plugins/run-store-sql.js +44 -16
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +3 -1
- package/dist/plugins/scenario-prefix-switch-m42.js +4 -3
- package/dist/plugins/schema-consistency.d.ts +89 -5
- package/dist/plugins/schema-consistency.js +176 -7
- package/dist/plugins/schema-drift-sentence.d.ts +6 -5
- package/dist/plugins/schema-drift-sentence.js +13 -5
- package/dist/plugins/session-placement.d.ts +5 -4
- package/dist/plugins/shell-sentinel-owner-m48.d.ts +22 -0
- package/dist/plugins/shell-sentinel-owner-m48.js +6 -0
- package/dist/plugins/stop-then-start-sentence.d.ts +16 -0
- package/dist/plugins/stop-then-start-sentence.js +7 -0
- package/dist/plugins/store-backend.d.ts +22 -8
- package/dist/plugins/store-backend.js +58 -24
- package/dist/plugins/store-contracts.d.ts +33 -3
- package/dist/plugins/store-contracts.js +16 -0
- package/dist/plugins/tidb-pool.d.ts +11 -6
- package/dist/plugins/tidb-pool.js +18 -12
- package/dist/plugins/workspace-custody.d.ts +44 -0
- package/dist/plugins/workspace-custody.js +47 -0
- package/dist/project-identity.d.ts +8 -7
- package/dist/project-identity.js +40 -17
- package/dist/project-layer-key.d.ts +13 -2
- package/dist/project-layer-key.js +9 -1
- package/dist/read-deny-floor-notice.d.ts +36 -0
- package/dist/read-deny-floor-notice.js +40 -0
- package/dist/{plain-string-record.d.ts → request-declaration-disposition.d.ts} +9 -23
- package/dist/request-declaration-disposition.js +39 -0
- package/dist/run-cancel-card.d.ts +28 -0
- package/dist/run-cancel-card.js +19 -0
- package/dist/run-cancel-context.d.ts +10 -0
- package/dist/run-cancel-context.js +1 -0
- package/dist/run-local.js +28 -13
- package/dist/runs.d.ts +31 -7
- package/dist/runs.js +34 -16
- package/dist/security.d.ts +2 -2
- package/dist/server-secret-env.d.ts +34 -20
- package/dist/server-secret-env.js +61 -18
- package/dist/session-agent.d.ts +3 -2
- package/dist/session-children-retire.d.ts +6 -3
- package/dist/session-children-retire.js +2 -5
- package/dist/session-workspace.d.ts +3 -3
- package/dist/store-admission.d.ts +33 -0
- package/dist/store-admission.js +49 -0
- package/dist/store-posture.d.ts +5 -0
- package/dist/store-posture.js +18 -1
- package/dist/stores-sql/checkpoint-store-sql.d.ts +1 -1
- package/dist/stores-sql/checkpoint-store-sql.js +3 -5
- package/dist/stores-sql/file-history-store-sql.d.ts +1 -1
- package/dist/stores-sql/file-history-store-sql.js +3 -5
- package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.js +4 -6
- package/dist/task-a2a.d.ts +3 -8
- package/dist/task-a2a.js +25 -27
- package/dist/task-cwd.d.ts +23 -7
- package/dist/task-cwd.js +3 -0
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-mcp.js +1 -1
- package/dist/task-settings.js +1 -0
- package/dist/terminal.d.ts +2 -0
- package/dist/terminal.js +21 -6
- package/dist/tool-approval.d.ts +44 -36
- package/dist/tool-approval.js +66 -47
- package/dist/trace/engine-notice-wire.d.ts +24 -21
- package/dist/trace/engine-notice-wire.js +7 -3
- package/dist/trace/ledger-sink.d.ts +3 -1
- package/dist/trace/project.d.ts +4 -2
- package/dist/trace/project.js +8 -7
- package/dist/trace/redact.d.ts +12 -0
- package/dist/trace/redact.js +5 -1
- package/dist/trace/self-minted-wire.d.ts +131 -52
- package/dist/trace/self-minted-wire.js +71 -39
- package/dist/web-admin-client/apply-effective.js +22 -9
- package/docs/error-text-lexicon.json +317 -0
- package/package.json +3 -1
- package/scripts/embed-minimal.mjs +183 -0
- package/wire-changes/server@7.149.0.json +372 -0
- package/dist/plain-string-record.js +0 -70
package/dist/config.js
CHANGED
|
@@ -4,9 +4,9 @@ import { DEFAULT_AT_MENTION, DEFAULT_MODEL_REF, mintCapabilityKeys } from "./mod
|
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { isAbsolute, join, posix as posixPath } from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import { hostOfUrl, HOST_UNREADABLE_SENTENCE, compileAllowList,
|
|
7
|
+
import { hostOfUrl, HOST_UNREADABLE_SENTENCE, compileAllowList, BUILTIN_COMPLIANCE_DENIES, COMPLIANCE_CAPABILITIES, CROSS_SESSION_INBOUND_SETTINGS, CROSS_SESSION_DIALOG_EXPIRY_VALUES, compileReadDeny, resolveReadDenyBuiltins, isModelPriced, PROTOCOL_TABLE, RECOMMENDED_SENSITIVE_PATTERNS, judgeRuleToolName, resolveFileHistoryRetention, resolveLockedKeys, validatePermissionRules, WRITE_PROTECTED_DEFAULT_TABLE, resolveWriteProtectedTable, principalInboxConsumerOf, carriesCredential, isReplicableScope, resolveBashTimeoutCaps } from "@sema-agent/core";
|
|
8
8
|
import { ROSTER_PRIMARY_ROLES, ROSTER_CHEAP_ROLES, WEB_ADMIN_ENV, retiredEnvRefusal, stripControlAndBidi } from "@sema-agent/settings-schema";
|
|
9
|
-
import { parseApprovalHmacKeys, parsePrincipalJwks } from "./auth-keys.js";
|
|
9
|
+
import { parseApprovalHmacKeys, parsePrincipalJwks, parseServiceAuthTokens } from "./auth-keys.js";
|
|
10
10
|
import { DEFAULT_ELICITATION_THROTTLE } from "./elicitation.js";
|
|
11
11
|
import { buildRuleListJudgeOptions } from "./permission-rule-list.js";
|
|
12
12
|
import { isV2ScopeKey, memoryReplicationCoverage, replicatesProjectLayersOf } from "./memory-scope.js";
|
|
@@ -27,7 +27,7 @@ import { resolveLocalDataRoot } from "./local-data-root.js";
|
|
|
27
27
|
import { buildWriteProtectionPosture } from "./write-protection.js";
|
|
28
28
|
import { RUN_STALE_SEC_DEFAULT } from "./run-stale-default.js";
|
|
29
29
|
import { normalizeSshFingerprint } from "./ssh-host-key.js";
|
|
30
|
-
import {
|
|
30
|
+
import { resolveContextWindow } from "./model-context-window.js";
|
|
31
31
|
import { MODEL_THINKING_LEVELS, THINKING_LEVELS, THINKING_FORMATS, buildModelCompat, isModelThinkingLevel, isThinkingFormat, isThinkingTier } from "./model-compat.js";
|
|
32
32
|
import {} from "./posture-source.js";
|
|
33
33
|
import { COST_QUOTA_WINDOW_SEC_RANGE, costQuotaWindowSecInRange } from "./observability/cost-quota.js";
|
|
@@ -41,6 +41,7 @@ import { laneLivenessOf } from "./exec-bounds.js";
|
|
|
41
41
|
import { SANDBOX_IPV6_DEFAULT, SANDBOX_IPV6_WORDS } from "./sandbox-egress-policy.js";
|
|
42
42
|
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";
|
|
43
43
|
import { DEPLOYMENT_SHAPE_PREDICATES } from "./deployment-shape.js";
|
|
44
|
+
import { parseLocalStoreDurabilityWord } from "./local-store-declaration.js";
|
|
44
45
|
import { sandboxForwardedEnvOf } from "./execution-config-root.js";
|
|
45
46
|
import { SANDBOX_READ_FLOOR_DEFAULT, SANDBOX_READ_FLOOR_WORDS, laneMissingEnv, readDeclaredLaneTable } from "./execution-lane-caps.js";
|
|
46
47
|
import { MEMORY_ENGINE_BACKENDS, SESSION_BACKENDS, STORE_BACKENDS } from "@sema-agent/settings-schema/execution-lanes";
|
|
@@ -61,7 +62,7 @@ import { echoCallerText } from "./caller-text-echo.js";
|
|
|
61
62
|
import { PRINCIPAL_MAX_BYTES, principalShapeProblem } from "./principal-shape.js";
|
|
62
63
|
import { buildDisplaySafeUrl, redactSecrets } from "./trace/redact.js";
|
|
63
64
|
import { parseConfigLocalOwnerUid } from "./config-dir-trust.js";
|
|
64
|
-
import { allowlistedEnv, ownCredentialDeclarationRefusal } from "./server-secret-env.js";
|
|
65
|
+
import { allowlistedEnv, ownCredentialDeclarationRefusal, ownCredentialVariable } from "./server-secret-env.js";
|
|
65
66
|
import { ENV_NAME_ALLOWLIST_KNOBS, ENV_NAME_ALLOWLIST_KNOB_NAMES, describeAllowlistPostures } from "./env-name-allowlist-knobs.js";
|
|
66
67
|
import { APPROVAL_ASK_RETENTION_DEFAULT_MS, APPROVAL_ASK_RETENTION_FLOOR_MS } from "./approval-ask-retention.js";
|
|
67
68
|
import { parseModsDeclaration } from "./mods-declaration.js";
|
|
@@ -565,14 +566,18 @@ const OWN_CREDENTIAL_HANDOFF = {
|
|
|
565
566
|
"host-put-back": { where: "a put-back list hands the named variable back, as written, to the child the engine withheld it from", whom: "that child" },
|
|
566
567
|
"sandbox-grant": { where: "a sandbox list puts the named variable, as written, into a sandbox the model can read", whom: "the sandbox" },
|
|
567
568
|
};
|
|
568
|
-
function
|
|
569
|
-
|
|
569
|
+
function ownCredentialProblem(name, channel) {
|
|
570
|
+
const held = ownCredentialVariable(name);
|
|
571
|
+
if (held === undefined)
|
|
570
572
|
return undefined;
|
|
571
573
|
const { where, whom } = OWN_CREDENTIAL_HANDOFF[channel];
|
|
572
|
-
|
|
574
|
+
const copy = held === "value" ? "a copy under another name (its value is one of this service's credentials); " : "";
|
|
575
|
+
const engine = held === "name" ? "the engine refuses it on any allow list" : "the engine withholds it from every child";
|
|
576
|
+
return `this deployment's own credential — ${copy}${where}; give ${whom} a credential of its own (another name and another value) and list that name instead (${engine})`;
|
|
573
577
|
}
|
|
574
578
|
const NAMES_IN_FORCE = {
|
|
575
579
|
LSP_ENV_ALLOW: (c) => c.lspEnvAllow,
|
|
580
|
+
HOOK_ENV_ALLOW: (c) => c.hookEnvAllow,
|
|
576
581
|
E2B_SANDBOX_ENV: (c) => (c.remoteExec.provider === "e2b" ? Object.keys(sandboxForwardedEnvOf(c)) : []),
|
|
577
582
|
K8S_SANDBOX_ENV: (c) => (c.remoteExec.provider === "k8s" ? Object.keys(sandboxForwardedEnvOf(c)) : []),
|
|
578
583
|
DOCKER_SANDBOX_ENV: (c) => (c.remoteExec.provider === "local-docker" ? Object.keys(sandboxForwardedEnvOf(c)) : []),
|
|
@@ -583,7 +588,7 @@ export function sandboxEnvNamesInForce(seats) {
|
|
|
583
588
|
}
|
|
584
589
|
export function ownCredentialHitsInForce(seats) {
|
|
585
590
|
return SERVER_ENV_NAME_ALLOWLIST_KNOBS.flatMap((knob) => NAMES_IN_FORCE[knob](seats).flatMap((name) => {
|
|
586
|
-
const problem =
|
|
591
|
+
const problem = ownCredentialProblem(name, ENV_NAME_ALLOWLIST_KNOBS[knob].channel);
|
|
587
592
|
return problem === undefined ? [] : [{ knob, name, problem }];
|
|
588
593
|
}));
|
|
589
594
|
}
|
|
@@ -600,7 +605,7 @@ export function parseEnvNameAllowlist(knob, singleUserTurnkey) {
|
|
|
600
605
|
? 'not an environment-variable name (letters, digits and "_", not starting with a digit)'
|
|
601
606
|
: ENV_NAME_ALLOWLIST_KNOB_NAMES.has(seg.toUpperCase())
|
|
602
607
|
? `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)`
|
|
603
|
-
:
|
|
608
|
+
: ownCredentialProblem(seg, spec.channel);
|
|
604
609
|
if (problem === undefined)
|
|
605
610
|
return;
|
|
606
611
|
throw new Error(`env ${knob}: entry #${i + 1} of ${segments.length} is ${problem}` +
|
|
@@ -762,6 +767,7 @@ function optionalEnumKey(key, envName, raw, allowed) {
|
|
|
762
767
|
}
|
|
763
768
|
return { [key]: raw };
|
|
764
769
|
}
|
|
770
|
+
const PRINCIPAL_INBOX_ECHO_CHARS = 96;
|
|
765
771
|
function principalInboxAssistantKey(raw) {
|
|
766
772
|
if (raw === undefined || raw === "")
|
|
767
773
|
return {};
|
|
@@ -769,7 +775,9 @@ function principalInboxAssistantKey(raw) {
|
|
|
769
775
|
principalInboxConsumerOf({ principalInboxConsumer: { assistant: raw } });
|
|
770
776
|
}
|
|
771
777
|
catch (err) {
|
|
772
|
-
|
|
778
|
+
const shown = JSON.stringify(raw.length > PRINCIPAL_INBOX_ECHO_CHARS ? `${raw.slice(0, PRINCIPAL_INBOX_ECHO_CHARS)}…` : raw);
|
|
779
|
+
throw new Error(`env PRINCIPAL_INBOX_ASSISTANT must name the agent handle that consumes the principal inbox, or be unset or the empty string for no cross-principal delivery (a blank value is neither — whitespace is not "empty"): ` +
|
|
780
|
+
`the value ${shown} is refused — ${err instanceof Error ? err.message : String(err)}`);
|
|
773
781
|
}
|
|
774
782
|
return { principalInboxAssistant: raw };
|
|
775
783
|
}
|
|
@@ -975,6 +983,7 @@ function parseStoreDomain(ctx) {
|
|
|
975
983
|
return raw;
|
|
976
984
|
})()),
|
|
977
985
|
runStoreStrictHydrate: parseRunStoreStrictHydrate(process.env.RUN_STORE_STRICT_HYDRATE),
|
|
986
|
+
localStoreDurability: parseLocalStoreDurabilityWord(process.env.LOCAL_STORE_DURABILITY),
|
|
978
987
|
tidb: needsDb && dbBackend === "mysql"
|
|
979
988
|
? {
|
|
980
989
|
host: env("MYSQL_HOST"),
|
|
@@ -1085,7 +1094,7 @@ function parseModelDomain() {
|
|
|
1085
1094
|
});
|
|
1086
1095
|
const envCompat = envApi === "openai-completions" ? envCompatDeclared : undefined;
|
|
1087
1096
|
const modelCapability = { reasoning: parseBoolWord("MODEL_REASONING", process.env.MODEL_REASONING), vision: parseBoolWord("MODEL_VISION", process.env.MODEL_VISION) };
|
|
1088
|
-
const
|
|
1097
|
+
const mainWindow = resolveContextWindow(optNumEnvStrict("MODEL_CONTEXT_WINDOW"));
|
|
1089
1098
|
const model = {
|
|
1090
1099
|
id: modelId,
|
|
1091
1100
|
name: modelId,
|
|
@@ -1099,10 +1108,10 @@ function parseModelDomain() {
|
|
|
1099
1108
|
cacheRead: costEnv("MODEL_COST_CACHE_READ", "unset"),
|
|
1100
1109
|
cacheWrite: costEnv("MODEL_COST_CACHE_WRITE", "unset"),
|
|
1101
1110
|
}, undefined)),
|
|
1102
|
-
contextWindow,
|
|
1111
|
+
contextWindow: mainWindow.window,
|
|
1103
1112
|
maxTokens: process.env.MODEL_MAX_TOKENS !== undefined && process.env.MODEL_MAX_TOKENS !== ""
|
|
1104
1113
|
? parseNumOrFail("MODEL_MAX_TOKENS", process.env.MODEL_MAX_TOKENS)
|
|
1105
|
-
: Math.min(32000,
|
|
1114
|
+
: Math.min(32000, mainWindow.window),
|
|
1106
1115
|
...(optFinitePositiveEnv("MODEL_CHARS_PER_TOKEN") !== undefined ? { charsPerToken: optFinitePositiveEnv("MODEL_CHARS_PER_TOKEN") } : {}),
|
|
1107
1116
|
params: { promptCacheFamily: envLaneWire.promptCacheFamily },
|
|
1108
1117
|
...(thinkingDefault ? { defaultThinking: thinkingDefault } : {}),
|
|
@@ -1138,6 +1147,8 @@ function parseModelDomain() {
|
|
|
1138
1147
|
break;
|
|
1139
1148
|
}
|
|
1140
1149
|
const cheapMintedId = mintedCheapId(cheapSlot);
|
|
1150
|
+
const cheapDeclaredWindow = cheapMintedId === undefined ? undefined : optNumEnvStrict("MODEL_CHEAP_CONTEXT_WINDOW");
|
|
1151
|
+
const cheapWindow = resolveContextWindow(cheapDeclaredWindow, mainWindow);
|
|
1141
1152
|
const cheapModel = cheapMintedId !== undefined
|
|
1142
1153
|
? {
|
|
1143
1154
|
...model,
|
|
@@ -1150,7 +1161,7 @@ function parseModelDomain() {
|
|
|
1150
1161
|
cacheRead: costEnv("MODEL_CHEAP_COST_CACHE_READ", "declares-zero"),
|
|
1151
1162
|
cacheWrite: costEnv("MODEL_CHEAP_COST_CACHE_WRITE", "declares-zero"),
|
|
1152
1163
|
}, model.cost)),
|
|
1153
|
-
contextWindow:
|
|
1164
|
+
contextWindow: cheapWindow.window,
|
|
1154
1165
|
maxTokens: numEnvOr("MODEL_CHEAP_MAX_TOKENS", model.maxTokens),
|
|
1155
1166
|
...(optFinitePositiveEnv("MODEL_CHEAP_CHARS_PER_TOKEN") !== undefined ? { charsPerToken: optFinitePositiveEnv("MODEL_CHEAP_CHARS_PER_TOKEN") } : {}),
|
|
1156
1167
|
}
|
|
@@ -1172,7 +1183,7 @@ function parseModelDomain() {
|
|
|
1172
1183
|
if (cheapModel) {
|
|
1173
1184
|
const cheapAct = optFinitePositiveEnv("MODEL_CHEAP_AUTO_COMPACT_TOKENS");
|
|
1174
1185
|
if (applyAutoCompactWindow(cheapModel, cheapAct) === "removed-1m") {
|
|
1175
|
-
const inherited =
|
|
1186
|
+
const inherited = cheapDeclaredWindow === undefined;
|
|
1176
1187
|
CONFIG_NOTICES.push({
|
|
1177
1188
|
level: "warn",
|
|
1178
1189
|
event: "auto_compact_window_not_derived_1m",
|
|
@@ -1186,6 +1197,7 @@ function parseModelDomain() {
|
|
|
1186
1197
|
noticeAutoCompactAboveWindow("cheap", "MODEL_CHEAP_AUTO_COMPACT_TOKENS", cheapModel);
|
|
1187
1198
|
}
|
|
1188
1199
|
const models = envLaneTable(modelId, model, cheapModel);
|
|
1200
|
+
const contextWindowSources = Object.fromEntries(Object.entries(envLaneTable(modelId, { id: model.id, source: mainWindow.source }, cheapModel !== undefined ? { id: cheapModel.id, source: cheapWindow.source } : undefined)).map(([name, slot]) => [name, slot.source]));
|
|
1189
1201
|
const gatewayApiKey = route.gatewayApiKey;
|
|
1190
1202
|
if (gatewayBaseUrl === undefined && declaredCredential(gatewayApiKey) !== undefined) {
|
|
1191
1203
|
CONFIG_NOTICES.push({
|
|
@@ -1241,7 +1253,9 @@ function parseModelDomain() {
|
|
|
1241
1253
|
},
|
|
1242
1254
|
model,
|
|
1243
1255
|
envModel: model,
|
|
1256
|
+
envModelContextWindowSource: mainWindow.source,
|
|
1244
1257
|
models,
|
|
1258
|
+
contextWindowSources,
|
|
1245
1259
|
modelApiKeyEnv: {},
|
|
1246
1260
|
modelApiKeys: {},
|
|
1247
1261
|
modelRefusals: {},
|
|
@@ -1980,12 +1994,7 @@ function parseAuthDomain(ctx) {
|
|
|
1980
1994
|
const principalJwtIss = process.env.PRINCIPAL_JWT_ISS || undefined;
|
|
1981
1995
|
const principalJwtAud = process.env.PRINCIPAL_JWT_AUD || undefined;
|
|
1982
1996
|
const principalJwtMaxTtlSec = parseNumOrFailNonNegative("PRINCIPAL_JWT_MAX_TTL_SEC", env("PRINCIPAL_JWT_MAX_TTL_SEC", "120"));
|
|
1983
|
-
const authTokens =
|
|
1984
|
-
.split(",")
|
|
1985
|
-
.map((s) => s.trim())
|
|
1986
|
-
.filter((s) => s.includes("="))
|
|
1987
|
-
.map((s) => [s.slice(0, s.indexOf("=")).trim(), s.slice(s.indexOf("=") + 1).trim()])
|
|
1988
|
-
.filter(([tok, sys]) => tok.length > 0 && sys.length > 0));
|
|
1997
|
+
const authTokens = parseServiceAuthTokens(process.env.SERVICE_AUTH_TOKENS);
|
|
1989
1998
|
return {
|
|
1990
1999
|
bindHost: process.env.BIND_HOST || undefined,
|
|
1991
2000
|
bindHostSource: process.env.BIND_HOST ? "BIND_HOST" : undefined,
|
|
@@ -2028,6 +2037,7 @@ function parseOrchestrationDomain(ctx) {
|
|
|
2028
2037
|
const lspHostEnabled = boolEnv("LSP_HOST_ENABLED", true);
|
|
2029
2038
|
const autoBackgroundOnTimeout = boolEnv("AUTO_BACKGROUND_ON_TIMEOUT", true);
|
|
2030
2039
|
const lspEnvAllow = parseEnvNameAllowlist("LSP_ENV_ALLOW", singleUserTurnkey) ?? [];
|
|
2040
|
+
const hookEnvAllow = parseEnvNameAllowlist("HOOK_ENV_ALLOW", singleUserTurnkey) ?? [];
|
|
2031
2041
|
const declaredLane = declaredExecutionLane(process.env.REMOTE_EXEC);
|
|
2032
2042
|
const readFaceFacts = process.env.READ_FACE !== undefined
|
|
2033
2043
|
? { readFace: enumEnv("READ_FACE", "roots", ["open", "roots"]), readFaceSource: "env" }
|
|
@@ -2203,6 +2213,7 @@ function parseOrchestrationDomain(ctx) {
|
|
|
2203
2213
|
lspHostEnabled,
|
|
2204
2214
|
autoBackgroundOnTimeout,
|
|
2205
2215
|
lspEnvAllow,
|
|
2216
|
+
hookEnvAllow,
|
|
2206
2217
|
workflowAgentsReadOnly: boolEnv("WORKFLOW_AGENTS_READONLY", false),
|
|
2207
2218
|
imageBakes: {
|
|
2208
2219
|
enabled: boolEnv("IMAGE_BAKES_ENABLED", false),
|
|
@@ -2619,11 +2630,11 @@ function parseA2aServeAudience(v, at) {
|
|
|
2619
2630
|
}
|
|
2620
2631
|
const STORE_GROUP_KEYS = [
|
|
2621
2632
|
"sessionBackend", "sessionCacheTtlSec", "storeProbeIntervalMs", "storeLockWaitMs", "dbBackend", "dbBackendExplicit", "localDataRoot", "sealedKeyDir",
|
|
2622
|
-
"runStoreStrictHydrate",
|
|
2633
|
+
"runStoreStrictHydrate", "localStoreDurability",
|
|
2623
2634
|
"tidb", "pg", "dbQueryTimeoutMs", "snapshotBlobStore", "snapshotBlobSqlMaxBytes", "snapshotBlobAllowSql", "fileHistory", "fileHistoryCapture", "sendUserFile",
|
|
2624
2635
|
];
|
|
2625
2636
|
const MODEL_PLANE_GROUP_KEYS = [
|
|
2626
|
-
"gatewayBaseUrl", "gatewayApiKey", "gatewayFallbackUrls", "gatewayMaxRetries", "anthropic", "resilience", "model", "envModel", "models",
|
|
2637
|
+
"gatewayBaseUrl", "gatewayApiKey", "gatewayFallbackUrls", "gatewayMaxRetries", "anthropic", "resilience", "model", "envModel", "envModelContextWindowSource", "models", "contextWindowSources",
|
|
2627
2638
|
"modelApiKeyEnv", "modelApiKeys", "modelRefusals", "droppedCatalogEntries", "modelQuotaWeights", "tiers", "projects", "roles", "atMention", "cascadeLadder", "degrade",
|
|
2628
2639
|
];
|
|
2629
2640
|
const APPROVAL_GROUP_KEYS = [
|
|
@@ -2650,7 +2661,7 @@ const ORCHESTRATION_GROUP_KEYS = [
|
|
|
2650
2661
|
"workflowOrphanGraceMs", "workflowJournalRetentionMs", "workflowRunRetentionMs", "usageWindows", "workflowAgentsReadOnly",
|
|
2651
2662
|
"workflowSizeGuideline", "backgroundAgentRetentionMs", "backgroundAgentStaleRunningMs", "backgroundAgentStallMs",
|
|
2652
2663
|
"backgroundAgentParkClaimStaleMs", "delegationEntryCaps", "rosterRetentionMs", "leaderRunStaleMs", "scratchpadSweepTtlMs", "sandboxPkgSource", "sandboxPkgSourceCustom",
|
|
2653
|
-
"sessionAutoTitle", "sessionAutoTitleSource", "selectEnvironmentTool", "envFactsEnabled", "toolDeferLongtail", "lspHostEnabled", "lspEnvAllow", "autoBackgroundOnTimeout",
|
|
2664
|
+
"sessionAutoTitle", "sessionAutoTitleSource", "selectEnvironmentTool", "envFactsEnabled", "toolDeferLongtail", "lspHostEnabled", "lspEnvAllow", "hookEnvAllow", "autoBackgroundOnTimeout",
|
|
2654
2665
|
"imageBakes", "readFace", "readFaceSource", "taskWriteFaceEscalation", "readDenyPatterns", "readDenyBuiltinTiers", "readDenyBuiltinExclude", "readDenyFloorRequired", "sandboxReadFloor",
|
|
2655
2666
|
"agentConfigDir", "configLkgPath", "configLkgEnabled",
|
|
2656
2667
|
];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 「这只模型的窗是假定的」运维通告的**唯一发声器**(行的形与事件名属 `model-context-window.ts` 的 `buildContextWindowAssumedNotice`)。
|
|
3
|
+
*
|
|
4
|
+
* ## 说什么
|
|
5
|
+
* **进程此刻服务的那张模型表**里,窗来源(`config.contextWindowSources`,与 `GET /v1/models` 行的 `contextWindowSource` 同一张表)是 `assumed` 的每只模型一行;
|
|
6
|
+
* 一个名每进程只说一次(同一份活配置一本账 —— 起服说过的名,目录落地 / 「无中心配置」档回到 env 表时不再说)。
|
|
7
|
+
*
|
|
8
|
+
* ## 在哪说(位置即判据,与「配了 $ 天花板但目录未定价」那一句同一条纪律)
|
|
9
|
+
* · 起服:模型表**定形之后**(装配第 2 段目录应用之后的不变量区末尾、run-local 配置源应用之后的同一位置)—— 不在 `loadConfig` 里说:那一拍只见 env 表,
|
|
10
|
+
* 目录随后在 boot 被采纳时 env 表整张不服务,在那里说就是对一只不会服务的模型报警(行里还会说 `GET /v1/models` 有它的行,而那一行并不存在)。
|
|
11
|
+
* · 运行中:每次模型面 commit 之后(目录换代、迟到的 boot 目录、「无中心配置」档回到 env 表 —— `applyEffective` 一处)。
|
|
12
|
+
* 严格名册布防时 env 表是占位、从不被派发(`isRosterGateArmed`;路由判官对它豁免的同一个事实)⇒ env 表在服时不说。
|
|
13
|
+
*
|
|
14
|
+
* ## 哪些名
|
|
15
|
+
* 别名(`default` 与某个本名指向同一只模型)不另说;目录里真有一条**叫** `default` 的条目(不是别名)照说。
|
|
16
|
+
*/
|
|
17
|
+
import type { Model } from "@sema-agent/core";
|
|
18
|
+
import { type ContextWindowSource } from "./model-context-window.js";
|
|
19
|
+
/** 发声器读的那几格活配置(结构子集;`ServiceConfig` 满足)。 */
|
|
20
|
+
export interface AssumedWindowView {
|
|
21
|
+
readonly model: Model;
|
|
22
|
+
readonly envModel: Model;
|
|
23
|
+
readonly models: Readonly<Record<string, Model>>;
|
|
24
|
+
readonly contextWindowSources: Readonly<Record<string, ContextWindowSource>>;
|
|
25
|
+
}
|
|
26
|
+
export declare function warnAssumedContextWindows(config: AssumedWindowView, logger: {
|
|
27
|
+
warn(event: string, fields?: Record<string, unknown>): void;
|
|
28
|
+
} | undefined, opts: {
|
|
29
|
+
readonly envTableIsPlaceholder: boolean;
|
|
30
|
+
}): void;
|
|
31
|
+
//# sourceMappingURL=context-window-notice.d.ts.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { buildContextWindowAssumedNotice } from "./model-context-window.js";
|
|
2
|
+
import { DEFAULT_MODEL_REF, servedModelTableLeg } from "./model-select.js";
|
|
3
|
+
const assumedWindowNamesSaid = new WeakMap();
|
|
4
|
+
export function warnAssumedContextWindows(config, logger, opts) {
|
|
5
|
+
if (logger === undefined)
|
|
6
|
+
return;
|
|
7
|
+
const leg = servedModelTableLeg(config);
|
|
8
|
+
if (leg === "env" && opts.envTableIsPlaceholder)
|
|
9
|
+
return;
|
|
10
|
+
const said = assumedWindowNamesSaid.get(config) ?? new Set();
|
|
11
|
+
assumedWindowNamesSaid.set(config, said);
|
|
12
|
+
const named = new Set(Object.entries(config.models).filter(([name]) => name !== DEFAULT_MODEL_REF).map(([, m]) => m));
|
|
13
|
+
for (const [name, m] of Object.entries(config.models)) {
|
|
14
|
+
if (name === DEFAULT_MODEL_REF && named.has(m))
|
|
15
|
+
continue;
|
|
16
|
+
if (said.has(name) || config.contextWindowSources[name] !== "assumed")
|
|
17
|
+
continue;
|
|
18
|
+
said.add(name);
|
|
19
|
+
const declareAt = leg === "catalog"
|
|
20
|
+
? "the catalog entry's contextWindow (or MODEL_CONTEXT_WINDOW, which every entry without one inherits)"
|
|
21
|
+
: m === config.envModel
|
|
22
|
+
? "MODEL_CONTEXT_WINDOW"
|
|
23
|
+
: "MODEL_CHEAP_CONTEXT_WINDOW (or MODEL_CONTEXT_WINDOW, which the cheap slot inherits)";
|
|
24
|
+
const notice = buildContextWindowAssumedNotice({ model: name, window: m.contextWindow, declareAt });
|
|
25
|
+
logger.warn(notice.event, notice.fields);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=context-window-notice.js.map
|
|
@@ -105,36 +105,45 @@ export declare const DEPLOYMENT_SHAPE_PREDICATES: Readonly<{
|
|
|
105
105
|
principalRequired: DeploymentShapePredicate<"principal">;
|
|
106
106
|
/**
|
|
107
107
|
* 「这台部署有没有身份边界」的问法 —— 有 = 请求里有东西替主体作保或拦在门外:声明了 `REQUIRE_PRINCIPAL`,或配置接了任一已验身份来源
|
|
108
|
-
* (service 凭据 / 鉴权桥 issuer,含中心回退 / 直连门),或声明了只读 trace 凭据。没有 = dev-open
|
|
108
|
+
* (service 凭据 / 鉴权桥 issuer,含中心回退 / 直连门),或声明了只读 trace 凭据。没有 = dev-open:主体头是谁都能自报的(不是认证;报了它的请求仍为那位主体)。
|
|
109
109
|
* 只读配置(验签器在起服第 9 段按同一个配置读数建 ⇒「验签器在场」≡「配置里有桥」),所以先于验签器的起服段(第 3 段的一次性迁移)与请求面读到同一个答案。
|
|
110
|
-
* 读者:请求面的 dev-open 判据(`http/principal-gate.ts` 的 `devOpenDeployment
|
|
110
|
+
* 读者:请求面的 dev-open 判据(`http/principal-gate.ts` 的 `devOpenDeployment`,`actsForDeployment` 的一臂:不报主体的调用方在属主存取器的 fleet 一格与 `/metrics` 族上代部署本人)、
|
|
111
111
|
* 一次性迁移 M48 的输入(`plugins/store-backend.ts`:有边界 ⇒ 不改写哨兵属主)。
|
|
112
112
|
*/
|
|
113
|
-
identityBoundary: DeploymentShapePredicate<"
|
|
113
|
+
identityBoundary: DeploymentShapePredicate<"principal" | "identity">;
|
|
114
114
|
/**
|
|
115
115
|
* 租户轴的问法。今天与 {@link DEPLOYMENT_SHAPE_PREDICATES.principalRequired} 读**同一个声明**([ref] ①:托管 / 多租 ⇔ `REQUIRE_PRINCIPAL=true`,
|
|
116
116
|
* 签发方配置是身份验签轴、不算租户证据)—— 两个问题、一根轴、一个读口;「鉴权必需」与「多租形」拆成两个声明时只改这一行的判官。
|
|
117
117
|
*/
|
|
118
118
|
multiTenant: DeploymentShapePredicate<"principal">;
|
|
119
119
|
/** 读能力表 `callerCwd` 位(host = 单主才开;device = 路径落在发起者自己的设备上,归属由根会话行执行格上的设备绑定验过,不要求单主)。 */
|
|
120
|
-
callerCwd: DeploymentShapePredicate<"
|
|
120
|
+
callerCwd: DeploymentShapePredicate<"principal" | "lane">;
|
|
121
121
|
/** 调用方给的宿主绝对路径(附加目录 / 项目上下文 / 本机 SendUserFile / 指令文件探针)只在「手就在本 worker 的盘上 ∧ 单主」时指向调用方自己的东西;
|
|
122
|
-
* 本机语言服务器(`createLspManager`:本机子进程、在 worker 盘上找根)同问这一句,读这一行 × `LSP_HOST_ENABLED`。
|
|
123
|
-
|
|
122
|
+
* 本机语言服务器(`createLspManager`:本机子进程、在 worker 盘上找根)同问这一句,读这一行 × `LSP_HOST_ENABLED`。
|
|
123
|
+
* local 店的声明(`local-store-declaration.ts` 的 `localStoreDeclarationOf`)同问这一句:店的数据根就在这块盘上,盘是调用方自己的且易失 ⇒ 部署不替他声明它活过替换。 */
|
|
124
|
+
callerOwnsWorkerDisk: DeploymentShapePredicate<"principal" | "lane">;
|
|
124
125
|
/** wire `executionLane.toolsOnThisHost` 与出厂 / 中心技能的 `baseDir`:只问文件系统同一性,与租户无关(出厂内容每个租户拿到同一份)。 */
|
|
125
126
|
toolsOnThisHost: DeploymentShapePredicate<"lane">;
|
|
126
127
|
/** 无手形(声明 `none`;判据读执行环境块 `io`,不点名车道词)且单主:进程级消费者(hooks 命令、项目上下文本机读、卡批规则 root)看到的就是引擎自己的进程 cwd / env。 */
|
|
127
|
-
noHandsSingleUser: DeploymentShapePredicate<"
|
|
128
|
+
noHandsSingleUser: DeploymentShapePredicate<"principal" | "lane">;
|
|
128
129
|
/** 任务层替部署声明宿主姿态(bypassPermissions 开写面 / host shell 继承整份环境)的射程:device 车道上跨租户宿主穿越结构性不存在(clay 裁定③)。 */
|
|
129
|
-
taskHostPostureDeclarations: DeploymentShapePredicate<"
|
|
130
|
+
taskHostPostureDeclarations: DeploymentShapePredicate<"principal" | "lane">;
|
|
130
131
|
/** 写门走代理裁决(执行环境块 `hostLocalPaths` 为假:路径不是本 worker 盘上的文件);认不出的词 ⇒ 走代理(代理 slot 空 ⇒ 写门 fail-closed)。 */
|
|
131
132
|
sandboxPathAdjudication: DeploymentShapePredicate<"lane">;
|
|
132
133
|
/** 读能力表 `sandboxSendUserFile` 位(e2b / k8s 每任务一只沙箱 ⇒ 任何租户;ssh 共享一台真机 ⇒ 只单主)。 */
|
|
133
|
-
sandboxSendUserFile: DeploymentShapePredicate<"
|
|
134
|
+
sandboxSendUserFile: DeploymentShapePredicate<"principal" | "lane">;
|
|
134
135
|
/** 读能力表 `remoteScratchpad` 位(`/tmp/scratchpad/<sessionId>` 远端约定)。 */
|
|
135
136
|
remoteScratchpad: DeploymentShapePredicate<"lane">;
|
|
137
|
+
/**
|
|
138
|
+
* 读能力表 `backgroundShell` 位 —— 「这条车道的执行环境能不能开后台 shell(`run_in_background` / `BashOutput` / `KillShell`),含把运行中的前台命令领养成后台任务」的**唯一**答者:
|
|
139
|
+
* e2b / k8s 每任务一只沙箱 ⇒ 任何租户;host(命令落在 worker 宿主上的同一张进程表)⇒ 只单主;其余车道(含 none)没有后台 shell;认不出的车道 ⇒ 否。
|
|
140
|
+
* 读者(同读这一行,没有第二份判别式):三只声明后台 shell 的适配器的 `backgroundCapabilities`(`supported` 与 `supportsDetach` 是同一个答案)、
|
|
141
|
+
* host 适配器的装配点(`boot/execution-env.ts` / `run-local.ts` 把行的答案交给适配器的 `backgroundShell`)、能力事实 `autoBackgroundOnTimeout`(`/health.autoBackgroundOnTimeout`)。
|
|
142
|
+
* 全局关停开关 `HOST_BG_ENABLED` 不在行里 —— 它是旋钮不是部署形,host 适配器与事实在行之上各合取一次。
|
|
143
|
+
*/
|
|
144
|
+
backgroundShell: DeploymentShapePredicate<"principal" | "lane">;
|
|
136
145
|
/** 读能力表 `tenantSeparation` 位(值来自 settings-schema 车道词表正本);唯一读者 = 跨域不变量 `multi-tenant-shared-lane`。 */
|
|
137
|
-
laneSeparatesTenants: DeploymentShapePredicate<"
|
|
146
|
+
laneSeparatesTenants: DeploymentShapePredicate<"principal" | "lane">;
|
|
138
147
|
/**
|
|
139
148
|
* [ref] —— **VM 级**隔离强度(独立内核:e2b 的 Firecracker microVM;k8s 只在 Kata / gVisor 运行时类上)。与执行环境块 `isolation` 键
|
|
140
149
|
* (OS 级边界,容器即算;wire `executionLane.isolated` 的属主 `laneIsolated`)是两个问题,所以不叫「isolated」。读者:A 值路由。
|
|
@@ -157,7 +166,7 @@ export declare const DEPLOYMENT_SHAPE_PREDICATES: Readonly<{
|
|
|
157
166
|
* · `none`:没有执行环境(能力事实先判无手车道,这里照样表态)。
|
|
158
167
|
* 读者:能力事实 `sessionRewindFiles`(能力位与该口的 501 同读这一行)。
|
|
159
168
|
*/
|
|
160
|
-
rewindableWorkspace: DeploymentShapePredicate<"
|
|
169
|
+
rewindableWorkspace: DeploymentShapePredicate<"principal" | "lane">;
|
|
161
170
|
}>;
|
|
162
171
|
export {};
|
|
163
172
|
//# sourceMappingURL=deployment-shape.d.ts.map
|
package/dist/deployment-shape.js
CHANGED
|
@@ -63,6 +63,7 @@ export const DEPLOYMENT_SHAPE_PREDICATES = Object.freeze({
|
|
|
63
63
|
sandboxPathAdjudication: createPredicate(["lane"], "车道:写门的路径事实要经代理到执行环境里取(文件平面不在本 worker 盘上;认不出的车道也走代理)。", ({ lane }) => lane.block === undefined || !lane.block.hostLocalPaths),
|
|
64
64
|
sandboxSendUserFile: createPredicate(["lane", "principal"], "车道 × 租户:SendUserFile 的沙箱直传腿可以挂(沙箱盘 = 租户自己的任务工作区,或共享真机上的单主部署)。", ({ lane, principal }) => lane.caps !== undefined && capabilityHolds(lane.caps.sandboxSendUserFile, principal)),
|
|
65
65
|
remoteScratchpad: createPredicate(["lane"], "车道:执行环境里按会话分的远端 scratchpad 约定适用。", ({ lane }) => lane.caps !== undefined && lane.caps.remoteScratchpad === "supported"),
|
|
66
|
+
backgroundShell: createPredicate(["lane", "principal"], "车道 × 租户:本车道的执行环境可以开后台 shell(含领养运行中的前台命令)—— e2b / k8s 任何租户,host 只单主,其余车道没有。", ({ lane, principal }) => lane.caps !== undefined && capabilityHolds(lane.caps.backgroundShell, principal)),
|
|
66
67
|
laneSeparatesTenants: createPredicate(["lane", "principal"], "车道 × 租户:这条车道在这台部署上不让两个租户的命令落在同一个共享目标上(单主部署恒成立;认不出的车道不成立)。", ({ lane, principal }) => lane.caps !== undefined && capabilityHolds(lane.caps.tenantSeparation, principal)),
|
|
67
68
|
vmIsolatedHands: createPredicate(["lane"], "车道 / 隔离强度:手跑在 VM 级边界里(独立内核);runc / 共享内核 / 真机 / 认不出 ⇒ 否。", ({ lane }) => {
|
|
68
69
|
if (lane.lane === "e2b")
|
|
@@ -6,14 +6,15 @@
|
|
|
6
6
|
* · `example` 进拒句;
|
|
7
7
|
* · `multiTenant` = `REQUIRE_PRINCIPAL=true` 下名单作不作数 —— **只有服务进程读的旋钮有这一列**(姿态是服务进程的概念):
|
|
8
8
|
* - `LSP_ENV_ALLOW` ⇒ ignored:host 腿语言服务器在多租户姿态下本来就不起,名单无处作数,设了要说出来([ref])。
|
|
9
|
+
* - `HOOK_ENV_ALLOW` ⇒ ignored:请求的 `settings.hooks` 在多租户姿态下整只不跑(`task-settings.ts` `taskHooksHonored`,同一只部署形谓词),名单无处作数。
|
|
9
10
|
* - 三只沙箱名单(e2b / local-docker / k8s 各一只) ⇒ honored:[ref] 照录修前语义(任何姿态下都转发),[ref] 主会话裁定维持 —— 沙箱 env 是部署方为隔离沙箱显式配的
|
|
10
11
|
* 带外凭据(e2b / docker / k8s 车道本来就是多租户 fleet 的主形),与 LSP 那条「本机子进程」的形不同;多租户下起服说一句。
|
|
11
12
|
* · `BAKE_ENV_ALLOW`([ref] 残余,7.103.0)由 **bake-runner 进程**读(构建宿主守护进程:没有主体、没有租户 ⇒ 没有姿态列,
|
|
12
|
-
* 不进 {@link describeAllowlistPostures} 的姿态句)
|
|
13
|
-
* · `channel` = 这张名单**交给谁、在谁的减法之上**(闭集两词)
|
|
13
|
+
* 不进 {@link describeAllowlistPostures} 的姿态句)。它与服务侧五只旋钮同一只解析器、同一只「点名放行」谓词、同一条「原文按凭据类」律。
|
|
14
|
+
* · `channel` = 这张名单**交给谁、在谁的减法之上**(闭集两词)。它只定拒句里「交到哪里」那半句与出路的主语,**不定拒不拒**:「不许点哪些名」对六只一律
|
|
14
15
|
* = 名单型旋钮名 ∪ 本服务自有凭据名(引擎此刻的声明:起服解析时判一次,声明增长时由换代声明对活配置里每只服务侧名单此刻交出去的名重判一次;判官 = 引擎
|
|
15
16
|
* `inheritEnvPolicyProblem`,与引擎拒嵌入方白名单同句),规则全文在解析器头注 ②。
|
|
16
|
-
* - `host-put-back`(`LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW`)—— 剥后放回形:宿主子进程的 env 先经唯一组合(引擎扣掉本服务自有凭据 + 形状剥),
|
|
17
|
+
* - `host-put-back`(`LSP_ENV_ALLOW` / `HOOK_ENV_ALLOW` / `BAKE_ENV_ALLOW`)—— 剥后放回形:宿主子进程的 env 先经唯一组合(引擎扣掉本服务自有凭据 + 形状剥 / 严格名单),
|
|
17
18
|
* 名单点到的键再从本进程环境**原样**取回叠上去;点到本服务自有凭据名 = 把引擎刚扣下的那枚交回那只子进程。
|
|
18
19
|
* - `sandbox-grant`(三只沙箱名单)—— 沙箱 env 的唯一来源(沙箱不从本进程继承任何东西),部署方显式交出的带外凭据([ref] 照转发);
|
|
19
20
|
* 点到本服务自有凭据名 = 把它装进模型读得到的沙箱 env。沙箱要凭据 ⇒ 部署方给沙箱另铸一把(名与值都不同于本服务的任何凭据)。
|
|
@@ -25,7 +26,7 @@
|
|
|
25
26
|
* 当场撒谎。为什么是纯叶:`config-catalog.ts` 被 `config.ts` 值引,表留在 `config.ts` 会成装载环。
|
|
26
27
|
*/
|
|
27
28
|
/** 服务进程(`config.ts` `loadConfig`)读的名单型旋钮 —— 有多租户姿态。 */
|
|
28
|
-
export type ServerEnvNameAllowlistKnob = "LSP_ENV_ALLOW" | "E2B_SANDBOX_ENV" | "DOCKER_SANDBOX_ENV" | "K8S_SANDBOX_ENV";
|
|
29
|
+
export type ServerEnvNameAllowlistKnob = "LSP_ENV_ALLOW" | "HOOK_ENV_ALLOW" | "E2B_SANDBOX_ENV" | "DOCKER_SANDBOX_ENV" | "K8S_SANDBOX_ENV";
|
|
29
30
|
/** bake-runner 进程(`bake-runner/main.ts` `loadEnv`)读的名单型旋钮 —— 构建宿主守护进程没有主体 / 租户,没有姿态。 */
|
|
30
31
|
export type RunnerEnvNameAllowlistKnob = "BAKE_ENV_ALLOW";
|
|
31
32
|
export type EnvNameAllowlistKnob = ServerEnvNameAllowlistKnob | RunnerEnvNameAllowlistKnob;
|
|
@@ -52,7 +53,7 @@ export type EnvNameAllowlistKnobTable = {
|
|
|
52
53
|
readonly [K in EnvNameAllowlistKnob]: K extends ServerEnvNameAllowlistKnob ? ServerEnvNameAllowlistKnobRow : RunnerEnvNameAllowlistKnobRow;
|
|
53
54
|
};
|
|
54
55
|
export declare const ENV_NAME_ALLOWLIST_KNOBS: EnvNameAllowlistKnobTable;
|
|
55
|
-
/** 名单型旋钮的全部名字(
|
|
56
|
+
/** 名单型旋钮的全部名字(六只;表键派生)—— 两处用:解析器的「点名名单型旋钮 = 形错」、剥除的「名单原文按凭据类」臂。 */
|
|
56
57
|
export declare const ENV_NAME_ALLOWLIST_KNOB_NAMES: ReadonlySet<string>;
|
|
57
58
|
/**
|
|
58
59
|
* 多租户姿态句 —— **由表派生**,不许在别处手写。形:`under REQUIRE_PRINCIPAL=true: <旋钮> is ignored; <旋钮> / <旋钮> are forwarded as configured`
|
|
@@ -4,6 +4,11 @@ export const ENV_NAME_ALLOWLIST_KNOBS = {
|
|
|
4
4
|
channel: "host-put-back",
|
|
5
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" },
|
|
6
6
|
},
|
|
7
|
+
HOOK_ENV_ALLOW: {
|
|
8
|
+
example: "HOOK_ENV_ALLOW=HOOK_TOKEN,WEBHOOK_SIGNING_KEY",
|
|
9
|
+
channel: "host-put-back",
|
|
10
|
+
multiTenant: { kind: "ignored", why: "request settings hooks are not run in this posture, so no hook environment reads the list" },
|
|
11
|
+
},
|
|
7
12
|
E2B_SANDBOX_ENV: { example: "E2B_SANDBOX_ENV=GIT_TOKEN,NPM_TOKEN", channel: "sandbox-grant", multiTenant: { kind: "honored" } },
|
|
8
13
|
DOCKER_SANDBOX_ENV: { example: "DOCKER_SANDBOX_ENV=GIT_TOKEN,NPM_TOKEN", channel: "sandbox-grant", multiTenant: { kind: "honored" } },
|
|
9
14
|
K8S_SANDBOX_ENV: { example: "K8S_SANDBOX_ENV=GIT_TOKEN,NPM_TOKEN", channel: "sandbox-grant", multiTenant: { kind: "honored" } },
|
|
@@ -16,9 +16,8 @@ export type ExecutionLane = DeclarableLane;
|
|
|
16
16
|
export interface ExecutionLaneCaps {
|
|
17
17
|
/** 调用方送来的 `cwd` 是否被尊重。读者:部署形表行 `callerCwd`(本位即判据;改前对账 `task-cwd.ts` 的 `cwdHonored || deviceCwdHonored`)。 */
|
|
18
18
|
readonly callerCwd: LaneCapability;
|
|
19
|
-
/** core 的后台 shell 面(`run_in_background`/`BashOutput`/`KillShell`)
|
|
20
|
-
* `backgroundCapabilities
|
|
21
|
-
* `boot/execution-env.ts` 的 `hostCfg.backgroundShell`。 */
|
|
19
|
+
/** core 的后台 shell 面(`run_in_background`/`BashOutput`/`KillShell`),含把运行中的前台命令领养成后台任务(`supportsDetach`)。读者:部署形表行 `backgroundShell`(本位即判据);
|
|
20
|
+
* 三只适配器的 `backgroundCapabilities`(`supported` 与 `supportsDetach` 同一个答案)、host 适配器的装配点与事实 `autoBackgroundOnTimeout` 同读这一行,没有第二份判别式。 */
|
|
22
21
|
readonly backgroundShell: LaneCapability;
|
|
23
22
|
/** 自唤醒 scheduler(`CronCreate`/…)。判别式:`boot/execution-env.ts` host 臂的 `hostScheduler`
|
|
24
23
|
* 与 `http/routes/capabilities.ts` 的 `scheduler` 位(两处同判据)。 */
|
|
@@ -330,11 +329,27 @@ export declare function buildLaneHomeBootNote(deployment: LaneHomeDeployment): {
|
|
|
330
329
|
readonly event: string;
|
|
331
330
|
readonly note: string;
|
|
332
331
|
} | undefined;
|
|
332
|
+
/**
|
|
333
|
+
* 读拒表的字节地板不守时一条 run 的**两种结局**(闭集):`ran` = 部署没要求地板,run 照跑(引擎每 run 一条 `config.read_deny_floor_unkept` 通告);
|
|
334
|
+
* `refused` = 部署要求地板(`READ_DENY_FLOOR_REQUIRED=true`),run 在准备期拒(同码失败终局,同步提交 409)。判官只有引擎一只(`judgeReadFloorKept`),
|
|
335
|
+
* 结局由旋钮分开 —— 本仓只说话。
|
|
336
|
+
*/
|
|
337
|
+
export type ReadDenyFloorOutcome = "ran" | "refused";
|
|
338
|
+
/**
|
|
339
|
+
* **读拒字节地板不守的那一句** —— 本仓说这件事的**唯一**组句器(纯字符串 ⇒ `build*`):点名执行环境(`REMOTE_EXEC=<车道>`,运维写的那一格)、
|
|
340
|
+
* 「不守读拒字节地板」与出路 `READ_DENY_FLOOR_REQUIRED`。读它的面(一个事实一句话,不另写第二句):
|
|
341
|
+
* · `ran` —— run 事件流的 `engine_notice` 帧、运维 `engine_notice` 日志行与终局结果的 `readDenyFloor.message`(`read-deny-floor-notice.ts` 的呈现器);
|
|
342
|
+
* · `refused` —— 失败终局的句子(同步提交 409 的 `error`、run 行 `error`、`done` 帧 `terminal.message`,`terminal.ts` 的两只出口属主)与起服那一行
|
|
343
|
+
* `read_deny_floor_required_unkept` 的 `note`({@link buildReadDenyFloorUnkeptNote})。
|
|
344
|
+
* 句子不带行数(行数在通告的 `detail.rowCount`):同一条部署上同一种结局逐字同一句,运维能把起服行、409 与日志对上。
|
|
345
|
+
* 车道名以旋钮形 `REMOTE_EXEC=<词>` 出现 —— 那是调用方 / 运维写得出、查得到的名字,不是本仓对执行车道的自称。
|
|
346
|
+
*/
|
|
347
|
+
export declare function buildReadDenyFloorSentence(lane: string, outcome: ReadDenyFloorOutcome): string;
|
|
333
348
|
/**
|
|
334
349
|
* 「部署要求读拒表的字节地板(`READ_DENY_FLOOR_REQUIRED=true`),而本部署车道的执行环境块不守地板」时起服那一行的 `note`(纯字符串 ⇒ `build*`);否则 `undefined`。
|
|
335
350
|
* 判据只读部署的要求与 {@link capabilitiesFor} 的 `keepsReadFloor`(认不出的车道答不出块 ⇒ 按不守说,不静默)。`none` 的桩块守地板 ⇒ 不出。
|
|
336
|
-
*
|
|
337
|
-
*
|
|
351
|
+
* 句子 = 这条车道上每条被拒的 run 的拒句({@link buildReadDenyFloorSentence} 的 `refused`,一字不差):起服先把后果与两条出路说出来,
|
|
352
|
+
* 运维不必从第一条 409 才知道,且起服行与 409 是同一句。
|
|
338
353
|
*/
|
|
339
354
|
export declare function buildReadDenyFloorUnkeptNote(deployment: CapabilitiesDeployment & {
|
|
340
355
|
readonly readDenyFloorRequired: boolean;
|
|
@@ -327,14 +327,28 @@ export function buildLaneHomeBootNote(deployment) {
|
|
|
327
327
|
return { event: LANE_HOME_UNDECLARED_EVENT, note: buildHomeAbsentNote(homeLane, "REMOTE_EXEC_HOME_DIR is unset, and this lane cannot read its execution environment's home", DECLARE_HOME_REMEDY) };
|
|
328
328
|
return { event: LANE_HOME_UNMEASURED_EVENT, note: buildHomeUnmeasuredNote(homeLane, home) };
|
|
329
329
|
}
|
|
330
|
+
export function buildReadDenyFloorSentence(lane, outcome) {
|
|
331
|
+
const env = `the execution environment (REMOTE_EXEC=${lane}) does not keep the read-deny byte floor`;
|
|
332
|
+
switch (outcome) {
|
|
333
|
+
case "ran":
|
|
334
|
+
return (`This run's read-deny rules are not byte-enforced: ${env} — a path a rule refuses is refused when a command names it, ` +
|
|
335
|
+
`but a program a command runs can still open it (a recursive read under a directory reads the files below it, denied ones included), ` +
|
|
336
|
+
`and their bytes can reach the conversation. READ_DENY_FLOOR_REQUIRED is not set, so the run went ahead; set READ_DENY_FLOOR_REQUIRED=true to refuse such runs instead.`);
|
|
337
|
+
case "refused":
|
|
338
|
+
return (`READ_DENY_FLOOR_REQUIRED=true, and ${env} (a program a command runs could open a path a read-deny rule refuses): ` +
|
|
339
|
+
`a run with read-deny rules is refused before any command starts (config.read_deny_floor_unkept; a synchronous submit answers 409). ` +
|
|
340
|
+
`Run on an execution environment that keeps the floor, or unset READ_DENY_FLOOR_REQUIRED to let such runs go ahead with a notice.`);
|
|
341
|
+
default: {
|
|
342
|
+
const unhandled = outcome;
|
|
343
|
+
throw new Error(`unhandled read-deny floor outcome: ${String(unhandled)}`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
330
347
|
export function buildReadDenyFloorUnkeptNote(deployment) {
|
|
331
348
|
if (!deployment.readDenyFloorRequired)
|
|
332
349
|
return undefined;
|
|
333
350
|
if (capabilitiesFor(deployment)?.keepsReadFloor === true)
|
|
334
351
|
return undefined;
|
|
335
|
-
return (
|
|
336
|
-
`the read-deny table refuses). Every run whose read-deny table has rows — the shipped default tiers put rows there unless READ_DENY_BUILTIN_TIERS=none — ` +
|
|
337
|
-
`is refused before any command starts (config.read_deny_floor_unkept; a synchronous submit answers 409). ` +
|
|
338
|
-
`Either run on a lane that keeps the floor, or unset READ_DENY_FLOOR_REQUIRED to run with one operator notice per run instead.`);
|
|
352
|
+
return buildReadDenyFloorSentence(deployment.remoteExec.provider, "refused");
|
|
339
353
|
}
|
|
340
354
|
//# sourceMappingURL=execution-lane-caps.js.map
|
|
@@ -46,9 +46,14 @@ export type CommandSpawnPlan = {
|
|
|
46
46
|
export declare function composeHookEnvLayer(requestEnv: Readonly<Record<string, string>> | undefined, cwd: string, plugin: HookPluginContext | undefined): Record<string, string> & {
|
|
47
47
|
CLAUDE_PROJECT_DIR: string;
|
|
48
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* 这条 hook 的子进程会拿到的环境:有效环境层叠在继承那一半之上(组合属主 = `hook-runner.ts` 的 `hookChildEnv`,本模块不写第二份组合,只问它的读数)。
|
|
51
|
+
* 组合拒(授予形坏 / 放回点到本服务自有凭据名)⇒ 抛,起法按「起不来」答(与 spawn 时组合抛同一个结局)。
|
|
52
|
+
*/
|
|
53
|
+
export type HookChildEnvOf = (layer: Readonly<Record<string, string>>) => Readonly<Record<string, string | undefined>>;
|
|
49
54
|
/**
|
|
50
55
|
* 一条 command 条目的起法(规则见文件头)。`cwd` = 本次 hook 的工作目录(`CLAUDE_PROJECT_DIR` 的缺省值);`requestEnv` = 请求 `settings.env`(hook 环境的一层;**必传**:没有就显式传 `undefined`,
|
|
51
|
-
* 漏传是编译红,不会静默丢掉请求给的 env),合并与读法见 {@link composeHookEnvLayer} / {@link contextVarValue}。有副作用的只有两步,都只在条目带 `plugin` 时发生:读插件根是否是目录、建数据目录(CC 同:注入即建)。
|
|
56
|
+
* 漏传是编译红,不会静默丢掉请求给的 env),合并与读法见 {@link composeHookEnvLayer} / {@link contextVarValue};`childEnvOf` = 组合的读数入口({@link HookChildEnvOf})。有副作用的只有两步,都只在条目带 `plugin` 时发生:读插件根是否是目录、建数据目录(CC 同:注入即建)。
|
|
52
57
|
*/
|
|
53
|
-
export declare function planCommandSpawn(entry: RunnableCommandHookEntry, cwd: string, requestEnv: Readonly<Record<string, string>> | undefined): Promise<CommandSpawnPlan>;
|
|
58
|
+
export declare function planCommandSpawn(entry: RunnableCommandHookEntry, cwd: string, requestEnv: Readonly<Record<string, string>> | undefined, childEnvOf: HookChildEnvOf): Promise<CommandSpawnPlan>;
|
|
54
59
|
//# sourceMappingURL=command-spawn.d.ts.map
|
|
@@ -59,17 +59,24 @@ const refOf = (name) => "${" + name + "}";
|
|
|
59
59
|
export function composeHookEnvLayer(requestEnv, cwd, plugin) {
|
|
60
60
|
return { ...requestEnv, CLAUDE_PROJECT_DIR: requestEnv?.CLAUDE_PROJECT_DIR ?? cwd, ...hookPluginEnv(plugin) };
|
|
61
61
|
}
|
|
62
|
-
function contextVarValue(name,
|
|
63
|
-
const v =
|
|
62
|
+
function contextVarValue(name, env) {
|
|
63
|
+
const v = env[name];
|
|
64
64
|
return v !== undefined && v.length > 0 ? v : undefined;
|
|
65
65
|
}
|
|
66
|
-
export async function planCommandSpawn(entry, cwd, requestEnv) {
|
|
66
|
+
export async function planCommandSpawn(entry, cwd, requestEnv, childEnvOf) {
|
|
67
67
|
const texts = [entry.command, ...(entry.args ?? [])];
|
|
68
68
|
const p = entry.plugin;
|
|
69
69
|
const env = composeHookEnvLayer(requestEnv, cwd, p);
|
|
70
|
+
let seen;
|
|
71
|
+
try {
|
|
72
|
+
seen = childEnvOf(env);
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
return { kind: "refused", error: e instanceof Error ? e.message : String(e) };
|
|
76
|
+
}
|
|
70
77
|
const values = new Map([["CLAUDE_PROJECT_DIR", env.CLAUDE_PROJECT_DIR]]);
|
|
71
78
|
for (const [name, ref] of CONTEXT_VARS) {
|
|
72
|
-
const value = contextVarValue(name,
|
|
79
|
+
const value = contextVarValue(name, seen);
|
|
73
80
|
if (value !== undefined) {
|
|
74
81
|
values.set(name, value);
|
|
75
82
|
continue;
|
|
@@ -79,8 +86,8 @@ export async function planCommandSpawn(entry, cwd, requestEnv) {
|
|
|
79
86
|
return {
|
|
80
87
|
kind: "refused",
|
|
81
88
|
error: p !== undefined
|
|
82
|
-
? `hook command references ${ref} but only ${ROOT_REF} is available for this hook (it carries no plugin data directory and the
|
|
83
|
-
: `hook command references ${ref} but the hook is not associated with a plugin and the
|
|
89
|
+
? `hook command references ${ref} but only ${ROOT_REF} is available for this hook (it carries no plugin data directory and the hook environment does not set ${name}; a request can set it in settings.env)`
|
|
90
|
+
: `hook command references ${ref} but the hook is not associated with a plugin and the hook environment does not set ${name} (the variable is set for hooks that carry a plugin context; a request can set it in settings.env)`,
|
|
84
91
|
};
|
|
85
92
|
}
|
|
86
93
|
if (p !== undefined) {
|
|
@@ -533,6 +533,11 @@ export interface HookRunnerContext {
|
|
|
533
533
|
* `[]` = 没有层写名单(不限,与引擎外的参照实现「名单未设 ⇒ 不限」同读)。今天唯一的层来源是请求的 `settings`(`task-settings.ts` 的 `httpHookAllowlist`,源 `flagSettings`)。
|
|
534
534
|
*/
|
|
535
535
|
httpHookAllowlistLayers: readonly HttpHookAllowlistLayer[];
|
|
536
|
+
/**
|
|
537
|
+
* 部署方点名放回 hook 环境的服务进程变量名(`HOOK_ENV_ALLOW` 的生效名单,`config.hookEnvAllow`;读者 = {@link hookChildEnv} 的两个入口:命令腿 spawn 与 http 插值)。必填:每个装配点都要说 ——
|
|
538
|
+
* `[]` = 不放回(hook 环境 = 十二名基础名单 + 有效环境层)。这是服务进程变量进 hook 环境的**唯一**来源;请求层(条目 `allowedEnvVars`、`settings.httpHookAllowedEnvVars`)只收窄、不授予。
|
|
539
|
+
*/
|
|
540
|
+
hookEnvAllow: readonly string[];
|
|
536
541
|
/**
|
|
537
542
|
* 部署座在**任务座之下**挂了链成员的站点式样(引擎的准入记录读出,`boot/deployment-mods.ts` 的 `belowTaskChainPatternsOf`)。必填:每个装配点都要说 ——
|
|
538
543
|
* `[]` = 任务座之下没有部署座的链成员(部署注册只在任务座之上、只有观察者,或没有部署注册)。读者 = PreToolUse 翻译的只许收紧({@link chainsBelowTaskOn};请求钩子两条车道在这些站上只许收紧)。
|