@sema-agent/server 7.116.1 → 7.118.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +195 -0
- package/USAGE.md +65 -41
- package/dist/approval-card.d.ts +82 -18
- package/dist/approval-card.js +46 -4
- package/dist/approval.d.ts +4 -12
- package/dist/approval.js +4 -26
- package/dist/boot/budget-tracing.js +2 -3
- package/dist/boot/config-center.d.ts +2 -2
- package/dist/boot/config-center.js +5 -7
- package/dist/boot/parked-revive-gate.d.ts +1 -7
- package/dist/boot/parked-revive-gate.js +2 -12
- package/dist/boot/resolve-spec.js +18 -16
- package/dist/boot/runner-deps.d.ts +5 -3
- package/dist/boot/runner-deps.js +6 -4
- package/dist/boot/stage-07-capability-layer.js +2 -2
- package/dist/brain.d.ts +17 -8
- package/dist/brain.js +10 -7
- package/dist/capabilities/hands-lane.d.ts +25 -0
- package/dist/capabilities/hands-lane.js +1 -1
- package/dist/capabilities/mcp-probe.d.ts +2 -2
- package/dist/config-catalog.js +3 -2
- package/dist/config-center/apply-effective.d.ts +6 -16
- package/dist/config-center/apply-effective.js +0 -6
- package/dist/config-center/facade.d.ts +1 -1
- package/dist/config-center/facade.js +1 -1
- package/dist/config-center/restart-signal.d.ts +1 -1
- package/dist/config-types.d.ts +12 -16
- package/dist/config.d.ts +32 -29
- package/dist/config.js +20 -27
- package/dist/deployment-governance.d.ts +13 -19
- package/dist/deployment-governance.js +7 -14
- package/dist/governance-overrides.d.ts +20 -0
- package/dist/governance-overrides.js +8 -0
- package/dist/host-decision.d.ts +83 -25
- package/dist/host-decision.js +31 -1
- package/dist/http/admission.js +13 -7
- package/dist/http/approval-sweeps.js +16 -13
- package/dist/http/checkpoint-ctx.d.ts +83 -24
- package/dist/http/checkpoint-ctx.js +68 -8
- package/dist/http/mcp-dial-deadline.d.ts +35 -0
- package/dist/http/mcp-dial-deadline.js +21 -0
- package/dist/http/memory-compliance-failure-reply.d.ts +11 -5
- package/dist/http/memory-compliance-failure-reply.js +17 -8
- package/dist/http/memory-store-refusal-reply.d.ts +14 -11
- package/dist/http/memory-store-refusal-reply.js +16 -5
- package/dist/http/resume-legs.js +18 -18
- package/dist/http/retired-skill-manifest.d.ts +1 -1
- package/dist/http/route-ctx.d.ts +3 -3
- package/dist/http/routes/approvals-assistant.js +21 -24
- package/dist/http/routes/capabilities.js +5 -3
- package/dist/http/routes/mcp-reconnect.d.ts +17 -0
- package/dist/http/routes/mcp-reconnect.js +6 -1
- package/dist/http/routes/memory-bundle.js +1 -1
- package/dist/http/routes/memory-compliance.js +1 -1
- package/dist/http/routes/memory-origin.js +1 -1
- package/dist/http/routes/runs.js +53 -33
- package/dist/http/routes/sessions.d.ts +1 -1
- package/dist/http/routes/sessions.js +3 -6
- package/dist/http/routes/workflows.js +2 -0
- package/dist/http/wire-types.d.ts +6 -1
- package/dist/memory-store-refusal.d.ts +42 -17
- package/dist/memory-store-refusal.js +25 -6
- package/dist/model-select.d.ts +16 -5
- package/dist/model-select.js +7 -3
- package/dist/model-unreachable-notice.d.ts +1 -1
- package/dist/namespaced-rule-name.d.ts +45 -39
- package/dist/namespaced-rule-name.js +36 -22
- package/dist/observability/corrupt-read-seat.d.ts +4 -0
- package/dist/observability/corrupt-read-seat.js +1 -0
- package/dist/observability/fail-open.d.ts +15 -3
- package/dist/observability/fail-open.js +15 -3
- package/dist/observability/permission-rule-events.d.ts +3 -0
- package/dist/observability/permission-rule-events.js +4 -0
- package/dist/observability/run-terminal.js +21 -1
- package/dist/operator-ask.d.ts +4 -1
- package/dist/orchestration/workflow-agent-session-index.d.ts +82 -59
- package/dist/orchestration/workflow-agent-session-index.js +80 -14
- package/dist/orchestration/workflow-completion-inbox.d.ts +5 -0
- package/dist/orchestration/workflow-completion-inbox.js +39 -17
- package/dist/orchestration/workflow-notify-journal.d.ts +1 -1
- package/dist/orchestration/workflow-notify-journal.js +7 -2
- package/dist/outbound-dispatcher.d.ts +47 -20
- package/dist/outbound-dispatcher.js +198 -23
- package/dist/parked-decide.d.ts +43 -48
- package/dist/parked-decide.js +54 -16
- package/dist/permission-rule-list.d.ts +20 -31
- package/dist/permission-rule-vocab.d.ts +4 -3
- package/dist/permission-rule-vocab.js +1 -1
- package/dist/plugins/approval-ask-store-sql.d.ts +17 -20
- package/dist/plugins/approval-ask-store-sql.js +0 -3
- package/dist/plugins/one-time-migrations.d.ts +25 -0
- package/dist/plugins/one-time-migrations.js +192 -6
- package/dist/plugins/pg-pool.js +1 -1
- package/dist/plugins/tidb-pool.js +1 -1
- package/dist/plugins/web-search.d.ts +20 -1
- package/dist/plugins/web-search.js +39 -10
- package/dist/plugins/workflow-run-store-sql.d.ts +7 -6
- package/dist/plugins/workflow-run-store-sql.js +5 -7
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +1 -1
- package/dist/router/route-orchestration.d.ts +2 -23
- package/dist/rule-entry-list.d.ts +88 -0
- package/dist/rule-entry-list.js +102 -0
- package/dist/rules-consent.js +3 -0
- package/dist/run-local.d.ts +4 -2
- package/dist/run-local.js +4 -3
- package/dist/runs.d.ts +1 -1
- package/dist/runs.js +1 -0
- package/dist/runtime-governance.d.ts +5 -21
- package/dist/runtime-governance.js +4 -8
- package/dist/session-policy-wire.d.ts +13 -12
- package/dist/session-policy-wire.js +11 -6
- package/dist/spec-fields.d.ts +13 -24
- package/dist/spec-fields.js +13 -17
- package/dist/standing-answer-grant.d.ts +14 -2
- package/dist/standing-answer-grant.js +8 -1
- package/dist/task-settings.d.ts +18 -18
- package/dist/task-settings.js +63 -32
- package/dist/tool-approval.d.ts +77 -145
- package/dist/tool-approval.js +80 -62
- package/dist/trace/core-keyset-guard.d.ts +6 -6
- package/dist/trace/engine-notice-wire.d.ts +4 -6
- package/dist/trace/engine-notice-wire.js +14 -1
- package/dist/trace/self-minted-wire.d.ts +16 -2
- package/dist/trace/self-minted-wire.js +7 -0
- package/dist/user-input-ledger.d.ts +24 -12
- package/dist/user-input-ledger.js +33 -14
- package/package.json +2 -2
- package/scripts/drain-check-local.mjs +103 -7
- package/scripts/drain-check.mysql.sql +59 -8
- package/scripts/drain-check.pg.sql +66 -10
|
@@ -10,7 +10,7 @@ function hostGateCwd(config, localRoot) {
|
|
|
10
10
|
return join(config.localDataRoot ?? localRoot, "parked-revive-unrooted");
|
|
11
11
|
}
|
|
12
12
|
export function createParkedReviveInheritedGate(deps) {
|
|
13
|
-
const { config, question,
|
|
13
|
+
const { config, question, logger, localRoot, approverSeat, memoryEngineRoot } = deps;
|
|
14
14
|
const slots = deps.slots ?? sandboxPathEnvSlots;
|
|
15
15
|
return async (row, identity) => {
|
|
16
16
|
const metadata = await chainMetadataOf(deps, row, identity);
|
|
@@ -26,17 +26,7 @@ export function createParkedReviveInheritedGate(deps) {
|
|
|
26
26
|
...homeBase,
|
|
27
27
|
}
|
|
28
28
|
: { env: createHostAdjudicationEnv(config, localRoot), ...homeBase };
|
|
29
|
-
const
|
|
30
|
-
const baseline = createApprovalBaselinePolicy(config, {
|
|
31
|
-
kind: "durable",
|
|
32
|
-
question,
|
|
33
|
-
...(approvalExemptionStore && rootSessionId
|
|
34
|
-
? {
|
|
35
|
-
exempt: (toolName) => approvalExemptionStore.has(rootSessionId, toolName),
|
|
36
|
-
onExempted: (toolName, rawToolName) => logger.info("approval_exempted", { sessionId: rootSessionId, toolName, rawToolName, leg: "parked_revive" }),
|
|
37
|
-
}
|
|
38
|
-
: {}),
|
|
39
|
-
});
|
|
29
|
+
const baseline = createApprovalBaselinePolicy(config, { kind: "durable", question });
|
|
40
30
|
const governed = applyRuntimeGovernance({ objective: "", toolPolicy: baseline }, createDeploymentGovernanceInputs(config, pathAdjudication, { engineDataRoot: memoryEngineRoot }));
|
|
41
31
|
return {
|
|
42
32
|
parentConstraints: [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { realpathSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { NodeExecutionEnv, QUESTION_AWAITS_RESUME, WRITE_EXEMPT_DIR_COVERS_ROOT_CODE, deriveAskEffective, expandTiers, modePolicyOf, resolveAskSeamForm
|
|
3
|
+
import { NodeExecutionEnv, QUESTION_AWAITS_RESUME, WRITE_EXEMPT_DIR_COVERS_ROOT_CODE, deriveAskEffective, expandTiers, modePolicyOf, resolveAskSeamForm } from "@sema-agent/core";
|
|
4
4
|
import { cappedCeiling } from "../budget.js";
|
|
5
5
|
import { centerPromptProvider, centerIdentityAssembled } from "../capabilities/center-prompts.js";
|
|
6
6
|
import { SessionEnvironmentSelection, selectEnvironmentTool } from "../capabilities/select-environment-tool.js";
|
|
@@ -10,7 +10,7 @@ import { stampHandsLane, toolPolicyForHands } from "../capabilities/hands-lane.j
|
|
|
10
10
|
import { buildNoticeLaneFacts, shouldDiscloseNoPersistentMemory, withNoPersistentMemoryNotice } from "../capabilities/memory-notice.js";
|
|
11
11
|
import { applyLongtailDefer } from "../capabilities/tool-defer.js";
|
|
12
12
|
import { assertGuardPatternsUsable, buildApprovalGrantNotice, buildOnlySensitiveBaselineWarning, createApprovalBaselinePolicy, createDeploymentGovernanceInputs } from "../deployment-governance.js";
|
|
13
|
-
import { singleUserAutoAcceptBaselineApplies } from "../approval.js";
|
|
13
|
+
import { gateIntentUnserviceableReason, singleUserAutoAcceptBaselineApplies } from "../approval.js";
|
|
14
14
|
import { acceptShellScratchpadDir, buildEnvFacts, egressForRemoteExec, ensureScratchpadDir, resumeFactsForLane, scratchpadCoveringTaskRoot } from "../env-facts.js";
|
|
15
15
|
import { FleetEventBus } from "../fleet/fleet-bus.js";
|
|
16
16
|
import { composeHooks, createTaskHooks } from "../hooks/hook-runner.js";
|
|
@@ -24,9 +24,10 @@ import { isRemoteScratchpadLane, remoteScratchpadDirFor } from "../plugins/remot
|
|
|
24
24
|
import { bindAttachmentsForTask } from "../plugins/task-attachment-store.js";
|
|
25
25
|
import { resourceSuspendOptIn } from "../resource-suspend.js";
|
|
26
26
|
import { isIsolatedExecEnv, routeServiceTask, supPostureOverrides } from "../router/route-orchestration.js";
|
|
27
|
+
import { tightenGoverned } from "../governance-overrides.js";
|
|
27
28
|
import { gateExecutionLane } from "../runtime-caps-resolver.js";
|
|
28
29
|
import { applyRuntimeGovernance, stripDelegationTools } from "../runtime-governance.js";
|
|
29
|
-
import { HttpError, encodeCheckpointScope } from "../security.js";
|
|
30
|
+
import { HttpError, createCodedHttpError, encodeCheckpointScope } from "../security.js";
|
|
30
31
|
import { memoryProjectKeyFor, memorySpecForRequest } from "../memory-scope.js";
|
|
31
32
|
import { inheritEnvFieldIssue, singleMemberOffFieldIssue } from "../request-value-closure.js";
|
|
32
33
|
import { a2aForScenario, mcpForScenario } from "../config-center/facade.js";
|
|
@@ -35,6 +36,7 @@ import { cwdHonored, deviceCwdHonored, effectiveHostWorkspace, inProcessSingleUs
|
|
|
35
36
|
import { assertRequestA2aUnlocked, resolveRequestA2a } from "../task-a2a.js";
|
|
36
37
|
import { assertRequestMcpContentOrigin, assertRequestMcpUnlocked, resolveRequestMcp } from "../task-mcp.js";
|
|
37
38
|
import { MAX_SETTINGS_OUTPUT_STYLE_CHARS, acceptAppendSystemPrompt, applyTaskSettings, effectivePermissionMode, effectiveThinking, hasConstitutionAnchors, parseTaskSettings, taskHooksHonored, providerDropsAppend, settingsPermissionBucketIssue, withPermissionMode } from "../task-settings.js";
|
|
39
|
+
import { skillDenyInertEntryOf } from "../rule-entry-list.js";
|
|
38
40
|
import { enableForkFromBody, normalizeRetainSubagentSessions, selfOrchestrationFromBody } from "../task-workflow.js";
|
|
39
41
|
import { redactSecrets } from "../trace/redact.js";
|
|
40
42
|
import { DeferredSandboxPathEnv, isSandboxPathAdjudicationLane, sandboxPathEnvSlots } from "./deferred-sandbox-path-env.js";
|
|
@@ -63,6 +65,9 @@ export function createResolveSpec(ctx) {
|
|
|
63
65
|
if (approvalGrantNotice)
|
|
64
66
|
logger.info(approvalGrantNotice.event, approvalGrantNotice.fields);
|
|
65
67
|
const resolveSpec = async (body, req, auth, opts) => {
|
|
68
|
+
const seatRefusal = gateIntentUnserviceableReason(config, checkpointStore !== undefined);
|
|
69
|
+
if (seatRefusal !== undefined)
|
|
70
|
+
throw createCodedHttpError(501, "capability.checkpoint_store_required", seatRefusal);
|
|
66
71
|
assertRequestMcpUnlocked(body.mcpServers, lockedKeys);
|
|
67
72
|
if (opts?.leg === "fresh")
|
|
68
73
|
assertRequestMcpContentOrigin(body.mcpServers);
|
|
@@ -104,6 +109,11 @@ export function createResolveSpec(ctx) {
|
|
|
104
109
|
if (bucketIssue)
|
|
105
110
|
throw new HttpError(400, bucketIssue.message, { code: "request.field_invalid", extra: bucketIssue.fields });
|
|
106
111
|
}
|
|
112
|
+
{
|
|
113
|
+
const skillDeny = skillDenyInertEntryOf(body);
|
|
114
|
+
if (skillDeny !== undefined)
|
|
115
|
+
throw new HttpError(400, skillDeny.message, { code: "request.field_invalid" });
|
|
116
|
+
}
|
|
107
117
|
assertRequestA2aUnlocked(body.a2aPeers, lockedKeys);
|
|
108
118
|
const gated = await gateScenarioAndAppend(body, auth, opts);
|
|
109
119
|
const effMode = effectivePermissionMode(body, gated.parsedSettings.settings);
|
|
@@ -313,7 +323,7 @@ export function createResolveSpec(ctx) {
|
|
|
313
323
|
return false;
|
|
314
324
|
if (headerStr(req?.headers["x-detach-on-disconnect"]) === "true")
|
|
315
325
|
return false;
|
|
316
|
-
const askForm = resolveAskSeamForm({}, approverSeat !== undefined ? { onAsk: approverSeat } : {});
|
|
326
|
+
const askForm = resolveAskSeamForm(body.approvalReach !== undefined ? { approvalReach: body.approvalReach } : {}, approverSeat !== undefined ? { onAsk: approverSeat } : {});
|
|
317
327
|
return deriveAskEffective(askForm.form, "unresolved") === "human_reachable";
|
|
318
328
|
};
|
|
319
329
|
const assembleSpecLiteral = (body, auth, req, opts, parts, effMode) => {
|
|
@@ -362,6 +372,7 @@ export function createResolveSpec(ctx) {
|
|
|
362
372
|
...(() => { const v = toolMaterializeStrategyFromBody(body.toolMaterializeStrategy); return v ? { toolMaterializeStrategy: v } : {}; })(),
|
|
363
373
|
...(typeof body.interactiveTools === "boolean" ? { interactiveTools: body.interactiveTools } : {}),
|
|
364
374
|
...(declaresInteractivePosture(body, req, opts) ? { interactionPosture: "interactive" } : {}),
|
|
375
|
+
...(body.approvalReach !== undefined ? { approvalReach: body.approvalReach } : {}),
|
|
365
376
|
...(typeof body.oneShot === "boolean" ? { oneShot: body.oneShot } : {}),
|
|
366
377
|
resilience: normalizeResilience(body.resilience, explicitOperatorOk(auth?.principal, config.operatorPrincipals)),
|
|
367
378
|
finalVerification: cap.finalVerification === true || body.finalVerification === true ? true : undefined,
|
|
@@ -449,16 +460,7 @@ export function createResolveSpec(ctx) {
|
|
|
449
460
|
a2a: resolveRequestA2a(a2aForScenario(config.a2aPeers, scenarioName), body.a2aPeers, config, logger),
|
|
450
461
|
promptProvider: centerDecls ? centerPromptProvider(centerDecls, scenarioName) : cap.promptProvider,
|
|
451
462
|
toolPolicy: toolPolicyForHands(hands, durableEnabled
|
|
452
|
-
? createApprovalBaselinePolicy(config, {
|
|
453
|
-
kind: "durable",
|
|
454
|
-
question: liveQuestionFace,
|
|
455
|
-
...(approvalExemptionStore && auth?.sessionId
|
|
456
|
-
? {
|
|
457
|
-
exempt: (toolName) => approvalExemptionStore.has(auth.sessionId, toolName),
|
|
458
|
-
onExempted: (toolName, rawToolName) => logger.info("approval_exempted", { sessionId: auth.sessionId, toolName, rawToolName }),
|
|
459
|
-
}
|
|
460
|
-
: {}),
|
|
461
|
-
})
|
|
463
|
+
? createApprovalBaselinePolicy(config, { kind: "durable", question: liveQuestionFace })
|
|
462
464
|
: singleUserAutoAcceptBaselineApplies(config)
|
|
463
465
|
? createApprovalBaselinePolicy(config, { kind: "absent" })
|
|
464
466
|
: undefined),
|
|
@@ -590,7 +592,7 @@ export function createResolveSpec(ctx) {
|
|
|
590
592
|
...(e.detail !== undefined ? { extra: { writeExemptDirCoversRoot: e.detail } } : {}),
|
|
591
593
|
});
|
|
592
594
|
}
|
|
593
|
-
throw new HttpError(422, `settings
|
|
595
|
+
throw new HttpError(422, `request settings cannot be applied as written: ${e.message}`);
|
|
594
596
|
}
|
|
595
597
|
}
|
|
596
598
|
if (governed.handsReadOnly === true && Array.isArray(governed.tools)) {
|
|
@@ -667,7 +669,7 @@ export function createResolveSpec(ctx) {
|
|
|
667
669
|
});
|
|
668
670
|
logger.info("orchestration_routed", { mode: decision.mode, reason: decision.reason, sessionId: auth?.sessionId ?? null });
|
|
669
671
|
if (decision.mode === "supervisor") {
|
|
670
|
-
return
|
|
672
|
+
return tightenGoverned(governed, supPostureOverrides());
|
|
671
673
|
}
|
|
672
674
|
}
|
|
673
675
|
return governed;
|
|
@@ -236,7 +236,7 @@ export interface RunnerDepsCtx {
|
|
|
236
236
|
}
|
|
237
237
|
/** [ref] A10 留档发现②:main runner `RunnerDeps` 与 main.ts subRunner 字面量之间此前手工重复
|
|
238
238
|
* 的 ~15 个键,类型标注见 {@link createSharedRunnerDeps} 头注。 */
|
|
239
|
-
export type SharedRunnerDeps = Pick<RunnerDeps, "brain" | "readFace" | "readDenyPatterns" | "readDenyBuiltinTiers" | "readDenyBuiltinExclude" | "memoryDelegationEvidence" | "memoryProvenance" | "memoryCapturePolicy" | "delegationEntryCaps" | "crossSessionInbound" | "crossSessionDialogExpiry" | "writeProtectedPaths" | "models" | "roles" | "tiers" | "pricing" | "tracer" | "promptSource" | "executionEnvFactory" | "lspManager" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "hooks" | "toolResultStore" | "checkpointStore" | "hands" | "sessionPolicyStore" | "usageWindows" | "usageWindowStore" | "memoryScopeAdmission" | "deploymentMemoryScopes" | "sharedMemoryStores" | "compliancePostureResolver" | "lockedConfig" | "retentionPolicy" | "onNotice" | "mcpRevocations">;
|
|
239
|
+
export type SharedRunnerDeps = Pick<RunnerDeps, "brain" | "readFace" | "readDenyPatterns" | "readDenyBuiltinTiers" | "readDenyBuiltinExclude" | "memoryDelegationEvidence" | "memoryProvenance" | "memoryCapturePolicy" | "delegationEntryCaps" | "crossSessionInbound" | "crossSessionDialogExpiry" | "writeProtectedPaths" | "allowedTools" | "models" | "roles" | "tiers" | "pricing" | "tracer" | "promptSource" | "executionEnvFactory" | "lspManager" | "backgroundAgentStore" | "mailboxStore" | "rosterStore" | "hooks" | "toolResultStore" | "checkpointStore" | "hands" | "sessionPolicyStore" | "usageWindows" | "usageWindowStore" | "memoryScopeAdmission" | "deploymentMemoryScopes" | "sharedMemoryStores" | "compliancePostureResolver" | "lockedConfig" | "retentionPolicy" | "onNotice" | "mcpRevocations">;
|
|
240
240
|
/**
|
|
241
241
|
* [ref] A10 留档发现②(review 2026-07-29,[ref]§三族A 同源修补的延续):main runner 的
|
|
242
242
|
* `RunnerDeps` 字面量(下方 `createRunnerDeps`)与 `main.ts` 里 subRunner 的 `new Runner({...})`
|
|
@@ -311,8 +311,10 @@ export declare function createEngineNoticeSeat(logger: {
|
|
|
311
311
|
* 「键为 undefined」与「键缺席」对引擎逐字等价)。**不复制引擎缺省**(`roots`/`static-face`/`carry`/`open`/
|
|
312
312
|
* CC parity 20/200 一个都不抄):上游改缺省之日起本仓不会成为第二份真源。
|
|
313
313
|
*/
|
|
314
|
-
export type DeploymentPostureSeats = Pick<RunnerDeps, "readFace" | "readDenyPatterns" | "readDenyBuiltinTiers" | "readDenyBuiltinExclude" | "memoryDelegationEvidence" | "memoryProvenance" | "memoryCapturePolicy" | "delegationEntryCaps" | "crossSessionInbound" | "crossSessionDialogExpiry" | "writeProtectedPaths">;
|
|
315
|
-
|
|
314
|
+
export type DeploymentPostureSeats = Pick<RunnerDeps, "readFace" | "readDenyPatterns" | "readDenyBuiltinTiers" | "readDenyBuiltinExclude" | "memoryDelegationEvidence" | "memoryProvenance" | "memoryCapturePolicy" | "delegationEntryCaps" | "crossSessionInbound" | "crossSessionDialogExpiry" | "writeProtectedPaths" | "allowedTools">;
|
|
315
|
+
/** 本族读的配置切面:席名与 config 键同名的那几席 + 运维 allow 表(席 `allowedTools` ← config `approvalGrant`,env 名 `APPROVAL_GRANT` 不改)。 */
|
|
316
|
+
export type DeploymentPostureConfig = Pick<ServiceConfig, Exclude<keyof DeploymentPostureSeats, "allowedTools"> | "approvalGrant">;
|
|
317
|
+
export declare function buildDeploymentPostureSeats(config: DeploymentPostureConfig): DeploymentPostureSeats;
|
|
316
318
|
export declare function createSharedRunnerDeps(ctx: SharedRunnerDepsCtx): SharedRunnerDeps;
|
|
317
319
|
export declare function createRunnerDeps(ctx: RunnerDepsCtx): RunnerDeps;
|
|
318
320
|
//# sourceMappingURL=runner-deps.d.ts.map
|
package/dist/boot/runner-deps.js
CHANGED
|
@@ -9,14 +9,14 @@ import { createHardenedVmRunner } from "../orchestration/hardened-vm-runner.js";
|
|
|
9
9
|
import { createWorkerHardenedVmRunner } from "../orchestration/hardened-vm-worker-runner.js";
|
|
10
10
|
import { WorkflowAgentRegistry } from "../orchestration/workflow-agent-steer.js";
|
|
11
11
|
import { resolveServedSession } from "../orchestration/workflow-completion-inbox.js";
|
|
12
|
-
import { defaultEngineNoticeRouter } from "../trace/engine-notice-wire.js";
|
|
12
|
+
import { defaultEngineNoticeRouter, presentNoticeDetail } from "../trace/engine-notice-wire.js";
|
|
13
13
|
import { WorkflowNotifyGate } from "../orchestration/workflow-notify-journal.js";
|
|
14
14
|
import { makeLoadProjectMemory, makeProbeInstructionSources } from "../project-memory.js";
|
|
15
15
|
import { createInstructionSourceSeat } from "../instruction-source-notice.js";
|
|
16
16
|
import { workflowModelAllowlistFor } from "../task-workflow.js";
|
|
17
17
|
import { buildCrossSessionInboundLayers, crossSessionDialogExpiryOf } from "../cross-session-settings.js";
|
|
18
18
|
import { createPeerDirectory } from "../peer-directory.js";
|
|
19
|
-
import {
|
|
19
|
+
import { storeFormRefusalInIncident } from "../memory-store-refusal.js";
|
|
20
20
|
import { coreFileHistoryCaptureSeat } from "../file-history-capture.js";
|
|
21
21
|
import { rewindFailureCode } from "../file-history-disclosure.js";
|
|
22
22
|
export function createRunnerDepsOnAsk(toolApproval) {
|
|
@@ -41,7 +41,8 @@ const PROMPT_CACHE_BREAK_LEVELS = new Map(Object.entries(PROMPT_CACHE_BREAK_CAUS
|
|
|
41
41
|
const CEILING_ORIGINS = new Set(["walltime", "turns"]);
|
|
42
42
|
export function createEngineNoticeForwarder(logger, router = defaultEngineNoticeRouter, metrics) {
|
|
43
43
|
return (notice) => {
|
|
44
|
-
|
|
44
|
+
const detail = presentNoticeDetail(notice.code, notice.detail);
|
|
45
|
+
logger.warn("engine_notice", { code: notice.code, message: notice.message, ...(detail !== undefined ? { detail } : {}) });
|
|
45
46
|
if (metrics !== undefined && notice.code === "task.interrupt_unconsumed") {
|
|
46
47
|
const origin = notice.detail?.origin;
|
|
47
48
|
if (typeof origin === "string" && CEILING_ORIGINS.has(origin))
|
|
@@ -68,6 +69,7 @@ export function buildDeploymentPostureSeats(config) {
|
|
|
68
69
|
crossSessionInbound: Object.keys(crossSessionLayers).length > 0 ? crossSessionLayers : undefined,
|
|
69
70
|
crossSessionDialogExpiry: crossSessionDialogExpiryOf(config),
|
|
70
71
|
writeProtectedPaths: config.writeProtectedPaths?.entries,
|
|
72
|
+
allowedTools: config.approvalGrant.length > 0 ? config.approvalGrant : undefined,
|
|
71
73
|
};
|
|
72
74
|
return seats;
|
|
73
75
|
}
|
|
@@ -195,7 +197,7 @@ export function createRunnerDeps(ctx) {
|
|
|
195
197
|
if (report.patches)
|
|
196
198
|
metrics.inc("memory_harvest_patches_total", { phase: info.phase }, (report.patches.add ?? 0) + (report.patches.update ?? 0));
|
|
197
199
|
if (report.incident) {
|
|
198
|
-
const code =
|
|
200
|
+
const code = storeFormRefusalInIncident(report.incident);
|
|
199
201
|
logger.warn("memory_harvest_incident", { kind: report.incident.kind, phase: info.phase, ...(code !== undefined ? { code } : {}) });
|
|
200
202
|
}
|
|
201
203
|
const byCode = new Map();
|
|
@@ -64,7 +64,7 @@ export async function runStage07(ctx) {
|
|
|
64
64
|
newId: uuidv7,
|
|
65
65
|
});
|
|
66
66
|
if (converged > 0)
|
|
67
|
-
logger.warn("user_input_ledger_crash_converged", { converged, note: "steers accepted with 200 \"applied\" by a previous process that ended before its run settled were converged as cause:crashed; each session's next run announces them (task.user_steer_undrained) and GET /v1/sessions/:id lists them under userInputUndrained" });
|
|
67
|
+
logger.warn("user_input_ledger_crash_converged", { converged, note: "steers accepted with 200 \"applied\" by a previous process that ended before its run settled were converged as cause:crashed; each session's next run announces them (task.user_steer_undrained, or task.user_followup_undrained for steers queued with priority later) and GET /v1/sessions/:id lists them under userInputUndrained" });
|
|
68
68
|
return ledger;
|
|
69
69
|
})()
|
|
70
70
|
: undefined;
|
|
@@ -166,7 +166,7 @@ export async function runStage07(ctx) {
|
|
|
166
166
|
const parkedReviveSurface = checkpointStore && backgroundAgentStore && builtinDefaultScenario ? createParkedReviveSurface(builtinDefaultScenario) : undefined;
|
|
167
167
|
const parkedReviveInheritedGate = parkedReviveSurface && config.durableApproval
|
|
168
168
|
? createParkedReviveInheritedGate({
|
|
169
|
-
config, question,
|
|
169
|
+
config, question, logger, localRoot,
|
|
170
170
|
memoryEngineRoot: memoryEngine?.root,
|
|
171
171
|
approverSeat: createRunnerDepsOnAsk(toolApproval),
|
|
172
172
|
...(runnerDeps.runtimeCapsResolver ? { resolveRuntimeCaps: runnerDeps.runtimeCapsResolver } : {}),
|
package/dist/brain.d.ts
CHANGED
|
@@ -11,7 +11,8 @@ import { type RestartSliceCtx } from "./config-center/restart-signal.js";
|
|
|
11
11
|
*/
|
|
12
12
|
export declare const FAST_FAIL_MAX_RETRIES = 2;
|
|
13
13
|
/**
|
|
14
|
-
* Build the external "Brain" (LLM) from config
|
|
14
|
+
* Build the external "Brain" (LLM) from config — and hand out, from the same assembly, the one reading that only the assembly knows: which
|
|
15
|
+
* reactive-degrade target the shell welded ({@link BrainAssembly.degradeRoute}). {@link createBrain} is the projection for callers that need only the brain.
|
|
15
16
|
*
|
|
16
17
|
* Composition (A1 + the 1.38 resilience stack, ordered timeout-innermost → breaker → failover-outermost):
|
|
17
18
|
* - **Tiered timeouts** (1.38; re-cut by core 7.33.0 along the segments of a call) are passed into each
|
|
@@ -39,6 +40,16 @@ export declare const FAST_FAIL_MAX_RETRIES = 2;
|
|
|
39
40
|
* transport's header / body clocks off too). The Model itself (id / contextWindow / maxTokens / provider) flows
|
|
40
41
|
* per-request through `Runner({ models })`.
|
|
41
42
|
*/
|
|
43
|
+
export declare function createBrainAssembly(config: ServiceConfig, deps?: {
|
|
44
|
+
fetchImpl?: typeof fetch;
|
|
45
|
+
breakerState?: BreakerState;
|
|
46
|
+
}): BrainAssembly;
|
|
47
|
+
/** {@link createBrainAssembly} 的产物:组好的 brain + 它的降级壳席(只有组装本身知道壳焊的是哪一只)。 */
|
|
48
|
+
export interface BrainAssembly {
|
|
49
|
+
readonly brain: Brain;
|
|
50
|
+
readonly degradeRoute: DegradeRouteWatch;
|
|
51
|
+
}
|
|
52
|
+
/** 只要 brain 的调用方(`run-local` / 旁路 lane / 测试台架)的投影 —— 与 {@link createBrainAssembly} 同一次组装。 */
|
|
42
53
|
export declare function createBrain(config: ServiceConfig, deps?: {
|
|
43
54
|
fetchImpl?: typeof fetch;
|
|
44
55
|
breakerState?: BreakerState;
|
|
@@ -84,16 +95,14 @@ export declare function degradeCredentialIdentityOf(config: Pick<ServiceConfig,
|
|
|
84
95
|
* 没有焊壳(车道没开 / 没有目标)⇒ `null`。在场 ↔ 缺席的翻转因此自然是一次变化。
|
|
85
96
|
*/
|
|
86
97
|
export declare function degradeRouteFingerprint(config: DegradeRoutePlane): unknown;
|
|
87
|
-
/**
|
|
98
|
+
/**
|
|
99
|
+
* `degrade-route` 片的席:boot 焊进去的那一只 vs 活配置此刻的同一只目标(`restartReasons` 的 `degradeRoute` 两侧读数)。`baked` 在 {@link createBrainAssembly}
|
|
100
|
+
* 焊壳的那一处算好、随装配产物交出 —— 不再有「紧随 createBrain 再捕获一次」的第二个出处。与 boot/memory-consolidation.ts `createConsolidationValveWatch` 同形
|
|
101
|
+
* (`{ read(): { baked, current } }`)。
|
|
102
|
+
*/
|
|
88
103
|
export interface DegradeRouteWatch {
|
|
89
104
|
read(): NonNullable<RestartSliceCtx["degradeRoute"]>;
|
|
90
105
|
}
|
|
91
|
-
/**
|
|
92
|
-
* `create*`:返回带捕获状态(组壳那一刻的指纹)的活对象。**须在 {@link createBrain} 的同一时刻、同一份 config 上调**
|
|
93
|
-
* (生产:boot/budget-tracing.ts 紧随 createBrain)—— 否则 `baked` 就不是壳真焊进去的那一只。与 boot/memory-consolidation.ts
|
|
94
|
-
* `createConsolidationValveWatch` 同形(`{ read(): { baked, current } }`)。
|
|
95
|
-
*/
|
|
96
|
-
export declare function createDegradeRouteWatch(config: DegradeRoutePlane): DegradeRouteWatch;
|
|
97
106
|
/**
|
|
98
107
|
* S-753 复审(opus F2 + codex C1)—— **failover 拓扑 × 首字节段没有部署窗**的启动期披露(纯数据,`build*`;告警由 boot 出)。
|
|
99
108
|
*
|
package/dist/brain.js
CHANGED
|
@@ -38,7 +38,7 @@ function constructRouteBrain(label, sourceUrls, construct) {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
const DEFAULT_RESILIENCE = buildDefaultResilience();
|
|
41
|
-
export function
|
|
41
|
+
export function createBrainAssembly(config, deps = {}) {
|
|
42
42
|
const { fetchImpl, breakerState } = deps;
|
|
43
43
|
const r = config.resilience ?? DEFAULT_RESILIENCE;
|
|
44
44
|
const timeouts = {
|
|
@@ -95,11 +95,13 @@ export function createBrain(config, deps = {}) {
|
|
|
95
95
|
let brain = anthropicBrain
|
|
96
96
|
? createRoutingBrain({ anthropic: anthropicBrain }, { fallback: gatewayBrain })
|
|
97
97
|
: gatewayBrain;
|
|
98
|
+
let degradeBaked = null;
|
|
98
99
|
if (config.degrade?.reactive) {
|
|
99
100
|
const degradeTo = config.degrade.to;
|
|
100
101
|
const fallbackModel = degradeTargetOf(config);
|
|
101
102
|
if (fallbackModel) {
|
|
102
103
|
const credential = degradeCredentialIdentityOf(config, fallbackModel);
|
|
104
|
+
degradeBaked = degradeWeldFingerprint(config, fallbackModel, credential);
|
|
103
105
|
const ownEnvRef = credential.apiKeyEnv !== undefined ? { [fallbackModel.name]: credential.apiKeyEnv } : {};
|
|
104
106
|
const ownSealed = credential.sealed !== undefined ? { [fallbackModel.name]: credential.sealed } : {};
|
|
105
107
|
const fbOwnApiKey = () => resolveModelApiKey(fallbackModel.name, ownEnvRef, process.env, ownSealed);
|
|
@@ -139,7 +141,10 @@ export function createBrain(config, deps = {}) {
|
|
|
139
141
|
});
|
|
140
142
|
}
|
|
141
143
|
}
|
|
142
|
-
return createModelReachBrain(brain);
|
|
144
|
+
return { brain: createModelReachBrain(brain), degradeRoute: { read: () => ({ baked: degradeBaked, current: degradeRouteFingerprint(config) }) } };
|
|
145
|
+
}
|
|
146
|
+
export function createBrain(config, deps = {}) {
|
|
147
|
+
return createBrainAssembly(config, deps).brain;
|
|
143
148
|
}
|
|
144
149
|
export function degradeTargetOf(config) {
|
|
145
150
|
return config.degrade?.reactive ? config.models?.[config.degrade.to] : undefined;
|
|
@@ -159,7 +164,9 @@ export function degradeRouteFingerprint(config) {
|
|
|
159
164
|
const target = degradeTargetOf(config);
|
|
160
165
|
if (target === undefined || config.degrade === undefined)
|
|
161
166
|
return null;
|
|
162
|
-
|
|
167
|
+
return degradeWeldFingerprint(config, target, degradeCredentialIdentityOf(config, target));
|
|
168
|
+
}
|
|
169
|
+
function degradeWeldFingerprint(config, target, credential) {
|
|
163
170
|
return {
|
|
164
171
|
model: catalogEntryFingerprint(target),
|
|
165
172
|
endpoint: openaiRouteBaseUrl(target.baseUrl, config.gatewayBaseUrl) ?? null,
|
|
@@ -174,10 +181,6 @@ function sealedIdentityFingerprint(sealed) {
|
|
|
174
181
|
return { poisoned: modelKeyPoisonIdentity(sealed), reason: sealed.reason };
|
|
175
182
|
return { digest: createHash("sha256").update(sealed, "utf8").digest("hex").slice(0, 16) };
|
|
176
183
|
}
|
|
177
|
-
export function createDegradeRouteWatch(config) {
|
|
178
|
-
const baked = degradeRouteFingerprint(config);
|
|
179
|
-
return { read: () => ({ baked, current: degradeRouteFingerprint(config) }) };
|
|
180
|
-
}
|
|
181
184
|
export function buildFailoverFirstByteNotice(config) {
|
|
182
185
|
const r = config.resilience ?? DEFAULT_RESILIENCE;
|
|
183
186
|
const fallbacks = config.gatewayFallbackUrls.length;
|
|
@@ -33,6 +33,31 @@ export interface HandsRunnerPair {
|
|
|
33
33
|
}
|
|
34
34
|
/** 按场景表态取 Runner。**穷举 switch**:`ScenarioHands` 加词而此处不改 = 编译错(无 default 臂)。 */
|
|
35
35
|
export declare function pickHandsRunner(hands: ScenarioHands, pair: HandsRunnerPair): Runner;
|
|
36
|
+
/**
|
|
37
|
+
* core 手带 band 的工具名**全集** —— 「挂 executionEnvFactory 才出现、不挂就消失」的那一批。
|
|
38
|
+
*
|
|
39
|
+
* 两段来源,都不是拍脑袋:
|
|
40
|
+
* · `handBandEffects()`(core 7.8.0 B1 起的导出面;此前是手抄表常量 `HAND_TOOL_EFFECTS`)—— band 的
|
|
41
|
+
* effect 表,由**静态工具目录**按 `mountedBy.includes("hands")` 派生。名册单源之后这张表不再是一张
|
|
42
|
+
* 手抄名表,加/退工具由目录一处说了算。
|
|
43
|
+
* · 下方锚定补集 —— `createHandsToolkit` / 手带块还会铸但**不在** effect 表里的 5 名(实测差集,见
|
|
44
|
+
* test/scenario-hands-lane.test.ts 的对表格:它用真 Runner 跑「有手 roster ∖ 无手 roster」,与本常量逐名对账,
|
|
45
|
+
* core 加/改 band 成员时红,防漂移)。
|
|
46
|
+
*
|
|
47
|
+
* ⚠️ 本全集是**观测口径**(用于防漂移对账),**不是** deny 名单 —— deny 用下面的
|
|
48
|
+
* {@link HANDS_EXCLUSIVE_TOOL_NAMES},理由见那里。
|
|
49
|
+
*
|
|
50
|
+
* 🚨 [ref] P0(2026-08-09):派生时必须过滤 core 的 `RETIRED_TOOL_NAMES` —— core 5.21.0 的
|
|
51
|
+
* `HAND_TOOL_EFFECTS` 里残留已退役的 `MultiEdit`,而 core `prepare-task` 的策略名审计见退役名
|
|
52
|
+
* **无条件 throw**(`config.legacy_tool_name`);不过滤,deny 名单一进 `spec.toolPolicy`,
|
|
53
|
+
* `hands: none` 三场景(scan/code-review/team)在**所有部署**上零 turn 全灭。core 5.21.1 已删
|
|
54
|
+
* 那条死条目([ref]),这道 filter 是结构性防御:将来 core 再退役任何 band 名都不会重演
|
|
55
|
+
* (test/scenario-hands-lane.test.ts 格7/格8 双钉:真 Runner 过审计 + 零交集门)。
|
|
56
|
+
* filter 打在**整表**(effect 表 + 锚定补集)之后 —— caret floor 下装置会解析到更新的 core,
|
|
57
|
+
* 补集名哪天被退役,只滤前半就是同一次故障换个名字(codex 复审 finding,2026-08-09)。
|
|
58
|
+
* S-1047(core 7.41.0 #1156):判据换成 core 导出的**那一只** `judgeRuleToolName`(策略名审计、会话规则店、本仓写口与配置表同调)——
|
|
59
|
+
* 修前这里直读 `RETIRED_TOOL_NAMES` 表,是本仓第三份「这是不是旧名」的手写判据。名册 = 空集(这张 deny 名单不挂在任何一跑的名册上判)。
|
|
60
|
+
*/
|
|
36
61
|
export declare const HANDS_BAND_TOOL_NAMES: readonly string[];
|
|
37
62
|
/**
|
|
38
63
|
* band 里**只有手才可能出现**的那批(= deny 名单)。
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { handBandEffects, judgeRuleToolName, combinePolicies, createAllowDenyPolicy } from "@sema-agent/core";
|
|
2
|
+
import { NO_DECLARED_TOOL_NAMES } from "../namespaced-rule-name.js";
|
|
2
3
|
export function withoutExecutionEnv(deps) {
|
|
3
4
|
const { executionEnvFactory: _handsDropped, ...rest } = deps;
|
|
4
5
|
return rest;
|
|
@@ -11,7 +12,6 @@ export function pickHandsRunner(hands, pair) {
|
|
|
11
12
|
return pair.handsless;
|
|
12
13
|
}
|
|
13
14
|
}
|
|
14
|
-
const NO_DECLARED_TOOL_NAMES = new Set();
|
|
15
15
|
export const HANDS_BAND_TOOL_NAMES = Object.freeze([
|
|
16
16
|
...handBandEffects().keys(),
|
|
17
17
|
"SendMessage",
|
|
@@ -79,7 +79,7 @@ export declare const MCP_PROBE_MAX_INFLIGHT = 32;
|
|
|
79
79
|
*
|
|
80
80
|
* 🔴 **不是新旋钮**:没有 env、不进 config-catalog、部署方改不了它 —— 「不新铸旋钮」这条要求管的是
|
|
81
81
|
* **旋钮**,不是常量。数值与既有 `GET /v1/sessions/:id/mcp` 面板的物化上界同阶(那边 10s),而**名字刻意
|
|
82
|
-
* 独立**:本仓 `sessions.ts`
|
|
82
|
+
* 独立**:本仓 `sessions.ts` 的同族时限(MCP / A2A / memory-status 各一枚)逐字写着理由 ——「两条腿的物化成本不同族,将来任一侧调窗时不该
|
|
83
83
|
* 被另一侧的名字绑架」。那边界的是**整次物化**,这边界的是**每台的裁决**,连语义都不是一回事。
|
|
84
84
|
*
|
|
85
85
|
* ⚠️ core 的硬条款(d.ts 逐字):`timeoutMs` 界**裁决**不界**拨号** —— 被时钟放弃的那次拨号仍在跑,
|
|
@@ -99,7 +99,7 @@ export declare const MCP_PROBE_VERDICT_TIMEOUT_MS = 10000;
|
|
|
99
99
|
* 与 core 自己成文的走查时长公式**逐字同形**(d.ts:"its own duration is those per-dial times summed over
|
|
100
100
|
* `ceil(n / concurrency)` rounds"),所以在一台**对端会答或会失败**的部署上这口钟结构上摸不到 —— 摸到它
|
|
101
101
|
* 就是真有一台对端在卡发送。读数:1 台 ⇒ 14s;32 台 ⇒ 44s。
|
|
102
|
-
* 兄弟先例:`GET /v1/sessions/:id/mcp` 面板的 `
|
|
102
|
+
* 兄弟先例:`GET /v1/sessions/:id/mcp` 面板的 `MCP_DIAL_DEADLINE_MS`(`http/mcp-dial-deadline.ts`;那边界的也是整次物化,但它是
|
|
103
103
|
* 一个定值;本面的申报条数由调用方决定,所以定值在这里就是那个「与所问无关的宽限」)。
|
|
104
104
|
* **纯数据** ⇒ `build*`。
|
|
105
105
|
*/
|
package/dist/config-catalog.js
CHANGED
|
@@ -11,6 +11,7 @@ import { MODEL_PROVIDER_WORDS } from "./model-provider.js";
|
|
|
11
11
|
import { buildDisplaySafeUrl } from "./trace/redact.js";
|
|
12
12
|
import { describeAllowlistPostures } from "./env-name-allowlist-knobs.js";
|
|
13
13
|
import { buildOutboundProxyPosture } from "./outbound-dispatcher.js";
|
|
14
|
+
import { modelSupportsImages } from "./model-select.js";
|
|
14
15
|
export const CATALOG_VALUE_TYPES = ["boolean", "number", "string", "enum", "csv", "json", "path", "url", "secret", "opaque"];
|
|
15
16
|
export const CATALOG_TIMINGS = ["hot", "restart", "deploy", "inert"];
|
|
16
17
|
export const CATALOG_DANGER_AXES = ["security", "billing", "data"];
|
|
@@ -58,7 +59,7 @@ export const CONFIG_CATALOG = [
|
|
|
58
59
|
r("ANTHROPIC_VERSION", "modelPlane", "string", "Anthropic API version 头(缺省由 SDK 定)"),
|
|
59
60
|
r("APPROVAL_AUTO_BUDGET", "approval", "number", "每 run-leg 自动放行的普通门控工具调用数上限(0=关;防审批循环的熔断,不是安全 ask 的帽)", { staticDefault: "0", danger: SEC, configKey: "approvalAutoBudget" }),
|
|
60
61
|
r("APPROVAL_DENY", "approval", "csv", "始终拒绝的工具名单(装配期拒不可匹配名)", { danger: SEC, configKey: "approvalDeny" }),
|
|
61
|
-
r("APPROVAL_GRANT", "approval", "csv", "运维的 allow
|
|
62
|
+
r("APPROVAL_GRANT", "approval", "csv", "运维的 allow 表(引擎 allow 层的部署成员 RunnerDeps.allowedTools,每只 Runner 同一席:HTTP 提交 / 续跑 / 停驻赎回 / run-local / leader 一律;规则文法 = 引擎的:工具名 / mcp__<server>__* / a2a__<peer>__* / Bash(<命令>) / Bash(<前缀>:*) / Read(//<dir>/**);命中 = 免问,清普通问与没人表态两类,内置工具也在内;清不掉任何一层的 deny / ask 规则、APPROVAL_NEVER_AUTO、shell 地板、写保护、治理、hook 的问、plan;不是白名单;引擎读成空的条目 / 服务器段铸不出 ⇒ 拒启)", { danger: SEC, configKey: "approvalGrant", derivedDefaultNote: "缺席 = 空表(本层不表态,折叠与未设逐字同)" }),
|
|
62
63
|
r("APPROVAL_HMAC_KEYS", "approval", "secret", "直连门(D-G)HMAC 完整性密钥集(空=直连门不激活)", { danger: SEC }),
|
|
63
64
|
r("APPROVAL_NEVER_AUTO", "approval", "csv", "永不被 AUTO_BUDGET 自动放行的工具集(不可逆动作恒要人)", { danger: SEC, configKey: "approvalNeverAuto" }),
|
|
64
65
|
r("APPROVAL_REQUIRE", "approval", "csv", "必须人审的工具名单(F4 门;center 腿热:refresh 拍整表换代,无 checkpoint 店的部署发非空名单 ⇒ 审批组整组拒)", { danger: SEC, configKey: "approvalRequire", center: cGov("approvalRequire") }),
|
|
@@ -318,7 +319,7 @@ export const CONFIG_CATALOG = [
|
|
|
318
319
|
},
|
|
319
320
|
}),
|
|
320
321
|
r("MODEL_VERIFIER", "modelPlane", "string", "verify 门的异构 verifier(须命中目录;typo 回 default 并 boot warn=自评自批)", { derivedDefaultNote: "缺席/不在目录 ⇒ default(=implementer,去相关性失效警告)" }),
|
|
321
|
-
r("MODEL_VISION", "modelPlane", "boolean", "主模型 vision 声明(false
|
|
322
|
+
r("MODEL_VISION", "modelPlane", "boolean", "主模型 vision 声明(false = 明说不收图:带图请求的图被换成占位句交给模型,提交时计数并告警)", { staticDefault: "true", resolve: (c) => modelSupportsImages(c.model), center: cModels("models[].vision") }),
|
|
322
323
|
r("MYSQL_DATABASE", "store", "string", "MySQL 协议库名(选中该引擎时必填)", { danger: DATA }),
|
|
323
324
|
r("MYSQL_HOST", "store", "string", "MySQL 协议主机(在场即算 SQL 信号,参与 DB_BACKEND 默认推导)", { danger: DATA }),
|
|
324
325
|
r("MYSQL_PASSWORD", "store", "secret", "MySQL 协议口令", { danger: SEC }),
|
|
@@ -81,7 +81,7 @@ export declare function applyEffective(config: ServiceConfig, eff: EffectiveConf
|
|
|
81
81
|
* 读者一律从这里派生,禁手抄:
|
|
82
82
|
* · stage:{@link stageModelPlane} 产出组内**每个**域的产物({@link ModelPlaneStages} 按本表映射),组被拒 ⇒ 一个域都没有;
|
|
83
83
|
* · 世代账:整组拒的 `keys` 与落地的 `applied` 都由 {@link MODEL_PLANE_SURFACES} 按本表派生({@link modelPlaneGroupReport});
|
|
84
|
-
* · boot 按组回落 LKG
|
|
84
|
+
* · boot 按组回落 LKG 的合成文档:{@link withModelPlaneOf}(`boot/config-center.ts`)。
|
|
85
85
|
* (与 `config.ts` 的配置组视图 `MODEL_PLANE_GROUP_KEYS` 不是一回事:那是 `ServiceConfig` 的分节视图;这里是「中心热应用的
|
|
86
86
|
* 模型面这一组包含哪些 effective 域」。)
|
|
87
87
|
*/
|
|
@@ -91,29 +91,19 @@ export type ModelPlaneDomain = (typeof MODEL_PLANE_DOMAINS)[number];
|
|
|
91
91
|
export type ModelPlaneOf = Pick<EffectiveConfig, ModelPlaneDomain>;
|
|
92
92
|
/**
|
|
93
93
|
* `target` 换上 `source` 的**整个模型面**(组内每个域都取 `source` 的;`source` 缺席的域在结果里同样缺席,不留 `target` 的),
|
|
94
|
-
* 其余域原样是 `target` 的。boot 按组回落 LKG
|
|
94
|
+
* 其余域原样是 `target` 的。boot 按组回落 LKG 的合成文档(回落 apply 的入参)走这一只 —— 禁在调用点
|
|
95
95
|
* 手写 `{ ...x, models, collab }`(漏一个域正是 V1 的病形)。纯数据:不改两个入参。
|
|
96
96
|
*/
|
|
97
97
|
export declare function withModelPlaneOf<E extends EffectiveConfig>(target: E, source: ModelPlaneOf): E;
|
|
98
|
-
/**
|
|
99
|
-
* **boot 快照**(restart 片的对照基线,`boot/config-center.ts` 的 `effective`)= 本次 boot 读到的那份(`read`:拉到的候选,或读回的盘上 LKG)
|
|
100
|
-
* 换上**真落地**的模型面 —— `appliedPlane` 是模型面组真落地的那一代(`read` 自己 / 按组回落的 LKG),`undefined` = 组被拒且没有可用的上一代
|
|
101
|
-
* (进程服务的是 env 表 ⇒「没有中心模型面」)。其余域恒是 `read` 的。
|
|
102
|
-
*
|
|
103
|
-
* boot 的两条落地路径(候选拉取、整份 LKG 读回)都经这一只,禁在调用点各写一份:S-789 的病形正是这句只在候选路径上成立(2d09c8e6),
|
|
104
|
-
* LKG 读回路径把被拒的 LKG 目录记成基线 ⇒ 修好的目录换掉降级目标时零 `degrade-route`,boot 焊死的降级壳永远指着 env 端点。
|
|
105
|
-
* S-794 起 `degrade-route` 片不再读快照的目录(改读降级壳 boot 焊的那只目标 vs 活配置,brain.ts `createDegradeRouteWatch`)——今天没有
|
|
106
|
-
* 重启片读快照的模型面;本函数保证的是快照本身说真话(进程真在服务的那一代),不让下一个读它的片重演 S-789。
|
|
107
|
-
* 纯数据:不改入参;模型面就是 `read` 自己那一代 ⇒ 原样交回(同一引用)。
|
|
108
|
-
*/
|
|
109
|
-
export declare function bootSnapshotOf<E extends EffectiveConfig>(read: E, appliedPlane: ModelPlaneOf | undefined): E;
|
|
110
98
|
/**
|
|
111
99
|
* E-1(7.103.1 修复轮,opus 腿):boot 读到的这一代**整套落地**了吗 —— 只有整套落地的那一代才可以成为 LKG(`latestEffective` /
|
|
112
100
|
* 盘上 LKG 候选)、才让它的 ETag 做条件请求(§9.5-2 + codex R2-F1)。三件同判,缺一不算:读腿没报坏域(`domainErrors`)、
|
|
113
101
|
* prompts 面过候选门同一只判形、apply 报告没有被整拒的组(`fullyApplied`;报告缺席 = 没 apply,dry-run 只判前两件)。
|
|
114
|
-
* boot 的两条落地路径(候选拉取、整份 LKG 读回)
|
|
102
|
+
* boot 的两条落地路径(候选拉取、整份 LKG 读回)与 refresh / 迟到 boot 两腿的 apply 之后都调这一只,禁在调用点各写一份(此前候选路径三件、LKG 路径只抄了一件,
|
|
103
|
+
* refresh / 迟到 boot 两腿各内联了第三件)。
|
|
115
104
|
* LKG 读回路径上前两件在上游已有门(`loadLkg` 的载荷复判拒坏 prompts;读回不产 `domainErrors`),这里同判是同一条规则的同一只谓词,
|
|
116
|
-
* 不是第二道门。refresh / 迟到 boot 两腿的候选门在 apply **之前**整拒坏域与坏 prompts(拒的是整份候选,不只是 LKG 推进)
|
|
105
|
+
* 不是第二道门。refresh / 迟到 boot 两腿的候选门在 apply **之前**整拒坏域与坏 prompts(拒的是整份候选,不只是 LKG 推进),所以到 apply 之后那两腿调本谓词时
|
|
106
|
+
* 前两件恒真、实判的是 `fullyApplied` 一件 —— 调它是为了「干净落地」只有这一个读法,不是再加一道门。
|
|
117
107
|
*/
|
|
118
108
|
export declare function fullyLandedForLkg(read: {
|
|
119
109
|
readonly effective: EffectiveConfig;
|
|
@@ -207,12 +207,6 @@ function takeModelPlaneDomain(out, source, d) {
|
|
|
207
207
|
else
|
|
208
208
|
out[d] = v;
|
|
209
209
|
}
|
|
210
|
-
function buildEnvOnlyModelPlane() {
|
|
211
|
-
return { models: { models: [], roles: {} } };
|
|
212
|
-
}
|
|
213
|
-
export function bootSnapshotOf(read, appliedPlane) {
|
|
214
|
-
return appliedPlane === read ? read : withModelPlaneOf(read, appliedPlane ?? buildEnvOnlyModelPlane());
|
|
215
|
-
}
|
|
216
210
|
export function fullyLandedForLkg(read, report) {
|
|
217
211
|
const prompts = read.effective.prompts;
|
|
218
212
|
return (read.domainErrors ?? []).length === 0 && (prompts === undefined || validatePromptsDomain(prompts).ok) && report?.fullyApplied !== false;
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
* importers to update, which was done in the same commit.
|
|
49
49
|
*/
|
|
50
50
|
export { fetchEffective, fetchPrincipalCaps, fetchPrincipalOrgMemory, ConfigCenterHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./http-client.js";
|
|
51
|
-
export { mutateInPlace, applyEffective, type ApplyReport, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff, MODEL_PLANE_DOMAINS, type ModelPlaneDomain, type ModelPlaneOf, withModelPlaneOf,
|
|
51
|
+
export { mutateInPlace, applyEffective, type ApplyReport, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff, MODEL_PLANE_DOMAINS, type ModelPlaneDomain, type ModelPlaneOf, withModelPlaneOf, fullyLandedForLkg, } from "./apply-effective.js";
|
|
52
52
|
export { restartReasons, modelPlaneChanged, type RestartSlice, type RestartSliceCtx, type EngineRestartSignal, } from "./restart-signal.js";
|
|
53
53
|
export { applyCenterSkills, resolveMcpServers, mcpForScenario, resolveA2aPeers, a2aForScenario } from "./skills-mcp.js";
|
|
54
54
|
export { applyCenterReadFace, CENTER_READ_FACE_LIVE_KEYS, type CenterReadFaceApply, type CenterReadFaceReport, type ReadFaceBaseline } from "./read-face.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { fetchEffective, fetchPrincipalCaps, fetchPrincipalOrgMemory, ConfigCenterHttpError, fetchSkillContent, fetchPromptArtifact, fetchPromptBlob, } from "./http-client.js";
|
|
2
|
-
export { mutateInPlace, applyEffective, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff, MODEL_PLANE_DOMAINS, withModelPlaneOf,
|
|
2
|
+
export { mutateInPlace, applyEffective, applyRuntimeGates, applyRuntimeHot, resolveDefaultModelName, logEffectiveDiff, MODEL_PLANE_DOMAINS, withModelPlaneOf, fullyLandedForLkg, } from "./apply-effective.js";
|
|
3
3
|
export { restartReasons, modelPlaneChanged, } from "./restart-signal.js";
|
|
4
4
|
export { applyCenterSkills, resolveMcpServers, mcpForScenario, resolveA2aPeers, a2aForScenario } from "./skills-mcp.js";
|
|
5
5
|
export { applyCenterReadFace, CENTER_READ_FACE_LIVE_KEYS } from "./read-face.js";
|
|
@@ -6,7 +6,7 @@ export type RestartSlice = "skills" | "mcp" | "a2a" | "scenarios" | "degrade-rou
|
|
|
6
6
|
* EffectiveConfig. Absent/empty = that lane is off ⇒ its slice is inert (null on both sides). */
|
|
7
7
|
export interface RestartSliceCtx {
|
|
8
8
|
/** S-794:反应式降级壳的两侧读数 —— `baked` = createBrain 组壳那一刻焊进去的目标路由指纹,`current` = 同一只
|
|
9
|
-
* 指纹函数(brain.ts `degradeRouteFingerprint`)对本拍活配置再读一次(
|
|
9
|
+
* 指纹函数(brain.ts `degradeRouteFingerprint`)对本拍活配置再读一次(`baked` 的出处见 brain.ts `createBrainAssembly`)。
|
|
10
10
|
* 缺席 = 调用方没有递席(单元调用)⇒ `degrade-route` 片恒不签;车道没开 / 没焊壳在席内表达为两侧同为 null。
|
|
11
11
|
* (此前的 `reactiveDegradeTo` 位只剩「阀门开着」一义,已并进本席 —— 一位不留两义。) */
|
|
12
12
|
degradeRoute?: {
|
package/dist/config-types.d.ts
CHANGED
|
@@ -1325,22 +1325,18 @@ export interface ServiceConfigFlat {
|
|
|
1325
1325
|
* 从未进入任何 policy。判定现在单源在 `hasOperatorGateIntent()`(与 inv#2 同文件)。 */
|
|
1326
1326
|
approvalNeverAuto: string[];
|
|
1327
1327
|
/**
|
|
1328
|
-
*
|
|
1329
|
-
*
|
|
1330
|
-
*
|
|
1331
|
-
*
|
|
1332
|
-
*
|
|
1333
|
-
*
|
|
1334
|
-
* ⚠️ 不是白名单:名字不叫 `…_ALLOW`,与会话规则的 `toolAllow`(「只许这些」)刻意分开 ——
|
|
1335
|
-
*
|
|
1336
|
-
*
|
|
1337
|
-
*
|
|
1338
|
-
*
|
|
1339
|
-
*
|
|
1340
|
-
* (`mcp__<server>__*`,含那台服务器将来新增的工具)= 对**每一个租户、每一条腿**的那些调用都不再因「没人表态」而问人,风险随规则的宽度走
|
|
1341
|
-
* (射程只到这一问:任何一层自己的问照旧压过它 —— 内置工具的精确名写进来,引擎的写门 / 形状层照问);补偿 = 本键就是
|
|
1342
|
-
* core 7.40.0 那条收紧的补偿,deny / ask(`APPROVAL_DENY` / `APPROVAL_REQUIRE` / 请求 settings / 会话规则)照旧压过它。
|
|
1343
|
-
* v1 只有 env 一个写入通道(无 config-center 座位,不进 settings-schema)。空表 = 本层不铸叶,折叠逐字与修前同。
|
|
1328
|
+
* **运维的 allow 表**(`APPROVAL_GRANT`,逗号分隔的 allow 规则)—— 7.117.0(core 7.42.0)起是引擎 allow 层的**部署成员** `RunnerDeps.allowedTools`:
|
|
1329
|
+
* 经部署姿态座席族(`boot/runner-deps.ts` `buildDeploymentPostureSeats`)交给本进程造的每一只 Runner(boot / run-local / leader),Runner 构造时读一次。
|
|
1330
|
+
* 命中 = 免问(core `decisionReason: "deployment_rule"`),清「普通问 + 没人表态」两类,内置工具也在内;清不掉任何一层的 deny、ask 规则、运维的强制类
|
|
1331
|
+
* (`APPROVAL_NEVER_AUTO` / `MANUAL_MODE_SHELL_GATE=always` / 写保护 / 治理)、hook 的问、plan 的问。文法 = 引擎的(工具名 / 协议名覆盖形 / `Bash(...)` 命令规则 /
|
|
1332
|
+
* `Read(//dir/**)`);坏值拒启(`config.ts` `approvalGrantRefusal`:不是字符串表 / 协议名对端段铸不出 / 引擎读成空的条目)。
|
|
1333
|
+
*
|
|
1334
|
+
* ⚠️ 不是白名单:名字不叫 `…_ALLOW`,与会话规则的 `toolAllow`(「只许这些」)刻意分开 —— 本键只放,不收窄任何东西。
|
|
1335
|
+
*
|
|
1336
|
+
* 三问(7.117.0 语义变宽):谁需要 = 没有请求体的腿(`run-local` / leader)上接了 MCP 服务器、或想一句话放掉自家某只工具的运维;谁受伤 = 表里写了内置工具名的部署
|
|
1337
|
+
* (7.115.0–7.116.x 本键只回答「没人表态」,`Bash` / `Write` 写进来什么也不放;本版起这两只不再问);补偿 = 起服行 `approval_grant_in_force` 的 note 写着当前效果、
|
|
1338
|
+
* `GET /v1/diagnostics/wiring` 的 `serverGates.approvalGrant`、`MIGRATION.md` 升级前必读一段;要某只工具必须问,用上面那几只本键清不掉的旋钮。
|
|
1339
|
+
* v1 只有 env 一个写入通道(无 config-center 座位,不进 settings-schema)= 进程常量,与 Runner 席位的寿命一致。空表 = 席位缺席(引擎读作「部署没有 allow 规则」)。
|
|
1344
1340
|
*/
|
|
1345
1341
|
approvalGrant: string[];
|
|
1346
1342
|
/** [ref] D-G (HMAC = integrity, not identity; ✅ WIRED — the "SCAFFOLD, not yet wired" note here was STALE,
|