@sema-agent/server 7.108.0 → 7.110.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 +60 -1
- package/README.md +8 -0
- package/README.zh-CN.md +5 -0
- package/USAGE.md +19 -29
- package/dist/approval-ask-machine.d.ts +9 -25
- package/dist/approval-ask-machine.js +5 -2
- package/dist/approval-card.d.ts +33 -3
- package/dist/approval-card.js +26 -2
- package/dist/bench/s1/live-deps.d.ts +4 -5
- package/dist/bench/s1/live-deps.js +9 -10
- package/dist/boot/leader.js +0 -2
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +3 -2
- package/dist/boot/resolve-spec.d.ts +1 -1
- package/dist/boot/resolve-spec.js +6 -12
- package/dist/boot/stage-07-capability-layer.d.ts +1 -0
- package/dist/boot/stage-07-capability-layer.js +17 -3
- package/dist/boot/stage-08-reapers.d.ts +1 -0
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +1 -0
- package/dist/boot/stage-10-http-server.d.ts +1 -0
- package/dist/boot/stage-10-http-server.js +2 -1
- package/dist/capabilities/scenarios.d.ts +3 -2
- package/dist/config-catalog.js +2 -4
- package/dist/config-provider.js +1 -0
- package/dist/config-types.d.ts +5 -11
- package/dist/config.js +21 -12
- package/dist/deployment-governance.d.ts +8 -2
- package/dist/deployment-governance.js +9 -8
- package/dist/hooks/hook-runner.d.ts +2 -2
- package/dist/hooks/hook-runner.js +40 -26
- package/dist/http/admission.js +8 -2
- package/dist/http/durable-run-leg.js +1 -1
- package/dist/http/resume-legs.js +6 -1
- package/dist/http/route-ctx.d.ts +3 -3
- package/dist/http/routes/capabilities.js +1 -0
- package/dist/http/routes/runs.d.ts +0 -1
- package/dist/http/routes/runs.js +22 -0
- package/dist/http/routes/sessions.js +12 -2
- package/dist/http/routes/tasks.js +5 -1
- package/dist/http/server.d.ts +7 -2
- package/dist/http/wire-types.d.ts +8 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/instruction-source-notice.d.ts +3 -3
- package/dist/leader/diffup.d.ts +53 -0
- package/dist/leader/diffup.js +95 -1
- package/dist/leader/leader.d.ts +0 -6
- package/dist/leader/leader.js +1 -1
- package/dist/leader/repair-wire.js +1 -1
- package/dist/leader/wire.d.ts +3 -10
- package/dist/leader/wire.js +39 -13
- package/dist/memory-layer-legacy-lock.d.ts +3 -3
- package/dist/model-entry-headers.d.ts +5 -2
- package/dist/model-entry-headers.js +4 -4
- package/dist/model-unreachable-notice.d.ts +2 -2
- package/dist/observability/corrupt-read-seat.d.ts +6 -0
- package/dist/observability/corrupt-read-seat.js +6 -0
- package/dist/observability/fail-open.d.ts +13 -5
- package/dist/observability/fail-open.js +13 -5
- package/dist/observability/metrics.js +2 -1
- package/dist/observability/run-terminal.js +10 -0
- package/dist/operator-ask.d.ts +9 -8
- package/dist/operator-ask.js +9 -1
- package/dist/plugins/approval-ask-store-file.d.ts +2 -1
- package/dist/plugins/approval-ask-store-file.js +3 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +2 -1
- package/dist/plugins/approval-ask-store-memory.js +7 -1
- package/dist/plugins/approval-ask-store-sql.d.ts +18 -0
- package/dist/plugins/approval-ask-store-sql.js +7 -0
- package/dist/plugins/file-run-store.js +2 -2
- package/dist/plugins/memory-run-store.d.ts +1 -1
- package/dist/plugins/memory-run-store.js +2 -1
- package/dist/plugins/pg-pool.js +15 -0
- package/dist/plugins/run-store-sql.d.ts +1 -1
- package/dist/plugins/run-store-sql.js +3 -2
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/store-backend.d.ts +4 -0
- package/dist/plugins/store-backend.js +8 -0
- package/dist/plugins/store-contracts.d.ts +7 -0
- package/dist/plugins/store-contracts.js +1 -0
- package/dist/plugins/tidb-pool.js +17 -0
- package/dist/plugins/user-input-ledger-file.d.ts +33 -0
- package/dist/plugins/user-input-ledger-file.js +98 -0
- package/dist/plugins/user-input-ledger-sql.d.ts +44 -0
- package/dist/plugins/user-input-ledger-sql.js +101 -0
- package/dist/request-key-closure.js +1 -1
- package/dist/run-local.d.ts +18 -5
- package/dist/run-local.js +26 -12
- package/dist/runs.d.ts +8 -1
- package/dist/runs.js +6 -2
- package/dist/runtime-governance.d.ts +23 -11
- package/dist/runtime-governance.js +7 -12
- package/dist/session-records-skipped-notice.d.ts +4 -3
- package/dist/task-settings.d.ts +0 -6
- package/dist/task-settings.js +0 -1
- package/dist/tool-approval.d.ts +44 -15
- package/dist/tool-approval.js +12 -8
- package/dist/trace/core-keyset-guard.d.ts +17 -2
- package/dist/trace/engine-notice-wire.d.ts +30 -35
- package/dist/trace/engine-notice-wire.js +23 -23
- package/dist/trace/project.js +2 -3
- package/dist/trace/self-minted-wire.d.ts +14 -0
- package/dist/trace/self-minted-wire.js +6 -0
- package/dist/unattended-permission-mode.d.ts +54 -93
- package/dist/unattended-permission-mode.js +8 -61
- package/dist/user-input-ledger.d.ts +296 -0
- package/dist/user-input-ledger.js +337 -0
- package/package.json +4 -4
package/dist/boot/reapers.js
CHANGED
|
@@ -56,7 +56,7 @@ export function createPlacementAwareReapSessions(deps) {
|
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
export function startReapers(ctx) {
|
|
59
|
-
const { config, logger, metrics, localRoot, backend, subRunner, runStore, checkpointStore, rateLimiter, costQuota, toolResultStore, fileHistoryErasure, taskAttachmentStore, imageBakes, worktreeReap, workflowNotifyGate, workflowRecoverOpts, workflowJournalStore, sqlWorkflowRunStore, workflowNotifyJournal, rosterStore, backgroundAgentStore, mailboxStore, toolApproval, permissionRuleStores, approvalNonceStore, getRunDenySweep, } = ctx;
|
|
59
|
+
const { config, logger, metrics, localRoot, backend, subRunner, runStore, checkpointStore, rateLimiter, costQuota, toolResultStore, fileHistoryErasure, taskAttachmentStore, imageBakes, worktreeReap, workflowNotifyGate, workflowRecoverOpts, workflowJournalStore, sqlWorkflowRunStore, workflowNotifyJournal, rosterStore, backgroundAgentStore, mailboxStore, toolApproval, permissionRuleStores, approvalNonceStore, getRunDenySweep, userInputLedger, } = ctx;
|
|
60
60
|
const leg = (p) => {
|
|
61
61
|
if (p !== undefined)
|
|
62
62
|
trackMaintenanceLeg(p);
|
|
@@ -196,7 +196,8 @@ export function startReapers(ctx) {
|
|
|
196
196
|
leg(runStore
|
|
197
197
|
?.reapStale(config.runStaleSec * 1000)
|
|
198
198
|
.then(reapCount("runs_reaped_total", { kind: "stale" }))
|
|
199
|
-
.then(() => runsReapStaleGuard.onSuccess(), runsReapStaleGuard.onError)
|
|
199
|
+
.then(() => runsReapStaleGuard.onSuccess(), runsReapStaleGuard.onError)
|
|
200
|
+
.then(() => userInputLedger?.converge().then(reapCount("user_input_converged_total", {}))));
|
|
200
201
|
if (checkpointStore) {
|
|
201
202
|
leg(checkpointStore
|
|
202
203
|
.reapExpired(Date.now())
|
|
@@ -17,7 +17,7 @@ import type { StoreBackend } from "../plugins/store-backend.js";
|
|
|
17
17
|
import { type TaskAttachmentStore } from "../plugins/task-attachment-store.js";
|
|
18
18
|
import { type createPrincipalEntitlementsClient } from "../runtime-caps-resolver.js";
|
|
19
19
|
import { type OwnerAwareSessionStore } from "../security.js";
|
|
20
|
-
import {
|
|
20
|
+
import type { RunnerDepsOnAsk } from "./runner-deps.js";
|
|
21
21
|
type PrincipalCaps = ReturnType<typeof createPrincipalEntitlementsClient>;
|
|
22
22
|
/** `resolveSpec` 原先从 `main()` 闭包里拿到的全部 boot 局部量。 */
|
|
23
23
|
export interface ResolveSpecCtx {
|
|
@@ -34,14 +34,13 @@ import { normalizeAttachments, normalizeResilience, normalizeResumeAtMode, norma
|
|
|
34
34
|
import { cwdHonored, deviceCwdHonored, effectiveHostWorkspace, inProcessSingleUserLane, isValidCwd, parseAdditionalDirectories, satisfiedByProcessCwd, shellEnvMismatchCount } from "../task-cwd.js";
|
|
35
35
|
import { assertRequestA2aUnlocked, resolveRequestA2a } from "../task-a2a.js";
|
|
36
36
|
import { assertRequestMcpContentOrigin, assertRequestMcpUnlocked, resolveRequestMcp } from "../task-mcp.js";
|
|
37
|
-
import {
|
|
37
|
+
import { MAX_SETTINGS_OUTPUT_STYLE_CHARS, acceptAppendSystemPrompt, applyTaskSettings, effectivePermissionMode, effectiveThinking, hasConstitutionAnchors, parseTaskSettings, providerDropsAppend, settingsPermissionBucketIssue, withPermissionMode } from "../task-settings.js";
|
|
38
38
|
import { enableForkFromBody, normalizeRetainSubagentSessions, selfOrchestrationFromBody } from "../task-workflow.js";
|
|
39
39
|
import { redactSecrets } from "../trace/redact.js";
|
|
40
40
|
import { DeferredSandboxPathEnv, isSandboxPathAdjudicationLane, sandboxPathEnvSlots } from "./deferred-sandbox-path-env.js";
|
|
41
41
|
import { executionLaneCaps, executionLaneHomeDir, executionLaneOf } from "../execution-lane-caps.js";
|
|
42
42
|
import { effectiveMemoryPersistenceCapable } from "./memory-boundary.js";
|
|
43
|
-
import {
|
|
44
|
-
import { createUnattendedLeg, unattendedPermissionMode, withUnattendedLeg } from "../unattended-permission-mode.js";
|
|
43
|
+
import { withUnattendedLeg } from "../unattended-permission-mode.js";
|
|
45
44
|
import { memoryFaceMounted } from "../memory-scope.js";
|
|
46
45
|
import { createAssemblyIncarnationRead, sessionFaceReaderOf } from "./session-incarnation-seat.js";
|
|
47
46
|
export function createResolveSpec(ctx) {
|
|
@@ -110,7 +109,7 @@ export function createResolveSpec(ctx) {
|
|
|
110
109
|
if (why !== undefined)
|
|
111
110
|
throw new HttpError(422, why, { code: HOST_POSTURE_REFUSED_CODE });
|
|
112
111
|
}
|
|
113
|
-
const lane = bindSettingsCwdEnvAndModel(body, auth, gated,
|
|
112
|
+
const lane = bindSettingsCwdEnvAndModel(body, auth, gated, opts);
|
|
114
113
|
if (auth?.sessionId && assemblyIncarnationRead)
|
|
115
114
|
noteSessionIncarnation(auth.sessionId, await assemblyIncarnationRead(auth.sessionId));
|
|
116
115
|
const anchors = await resolveHistoryAnchors(body, auth);
|
|
@@ -179,7 +178,7 @@ export function createResolveSpec(ctx) {
|
|
|
179
178
|
}
|
|
180
179
|
return { scenarioName, cap, hands: cap.hands, centerDecls, appendLessPack, acceptedAppend, objective, parsedSettings, attachmentNotice };
|
|
181
180
|
};
|
|
182
|
-
const bindSettingsCwdEnvAndModel = (body, auth, gated,
|
|
181
|
+
const bindSettingsCwdEnvAndModel = (body, auth, gated, opts) => {
|
|
183
182
|
const { objective, parsedSettings } = gated;
|
|
184
183
|
const cwdWriteGate = cwdHonored(config) || deviceCwdHonored(config);
|
|
185
184
|
const execLane = executionLaneOf(config.remoteExec?.provider);
|
|
@@ -219,7 +218,6 @@ export function createResolveSpec(ctx) {
|
|
|
219
218
|
logger,
|
|
220
219
|
sessionId: auth?.sessionId ?? "",
|
|
221
220
|
cwd: (auth?.sessionId ? perSessionCwd.get(auth.sessionId) : undefined) ?? process.cwd(),
|
|
222
|
-
permissionMode: effMode ?? ENGINE_ABSENT_PERMISSION_MODE,
|
|
223
221
|
...(parsedSettings.settings?.shellEnv ? { shellEnv: parsedSettings.settings.shellEnv } : {}),
|
|
224
222
|
hookLlm,
|
|
225
223
|
hookAgent,
|
|
@@ -440,7 +438,7 @@ export function createResolveSpec(ctx) {
|
|
|
440
438
|
const merged = extra.length > 0 ? [...(base ?? []), ...extra] : base;
|
|
441
439
|
return merged && config.toolDeferLongtail ? applyLongtailDefer(merged, true) : merged;
|
|
442
440
|
})(cap.tools),
|
|
443
|
-
skills: mergeUserSkills(cap.skills, body.skills, logger),
|
|
441
|
+
skills: body.disableSkills === true ? [] : mergeUserSkills(cap.skills, body.skills, logger),
|
|
444
442
|
...(parsedSettings.settings?.skillListingBudgetFraction !== undefined ? { skillListingBudgetFraction: parsedSettings.settings.skillListingBudgetFraction } : {}),
|
|
445
443
|
...(parsedSettings.settings?.skillListingMaxDescChars !== undefined ? { skillListingMaxDescChars: parsedSettings.settings.skillListingMaxDescChars } : {}),
|
|
446
444
|
mcp: resolveRequestMcp(mcpForScenario(config.mcpServers, scenarioName), body.mcpServers, config, logger, opts?.onNotice !== undefined ? { sessionId: auth?.sessionId, emit: opts.onNotice } : undefined),
|
|
@@ -670,15 +668,11 @@ export function createResolveSpec(ctx) {
|
|
|
670
668
|
}
|
|
671
669
|
return governed;
|
|
672
670
|
};
|
|
673
|
-
const resumeRunnerSeats = () => ({
|
|
674
|
-
...buildDeploymentPostureSeats(config),
|
|
675
|
-
...(memoryEngine !== undefined ? { memoryEngineDir: memoryEngine.root } : {}),
|
|
676
|
-
});
|
|
677
671
|
const resolveSpecForLeg = async (body, req, auth, opts) => {
|
|
678
672
|
const spec = await resolveSpec(body, req, auth, opts);
|
|
679
673
|
if (opts?.unattendedLeg !== true)
|
|
680
674
|
return spec;
|
|
681
|
-
return withUnattendedLeg(spec
|
|
675
|
+
return withUnattendedLeg(spec);
|
|
682
676
|
};
|
|
683
677
|
return resolveSpecForLeg;
|
|
684
678
|
}
|
|
@@ -23,6 +23,7 @@ export declare function runStage07(ctx: Awaited<ReturnType<typeof runStage06>>):
|
|
|
23
23
|
maxTurns: number | undefined;
|
|
24
24
|
};
|
|
25
25
|
taskTimeoutSec: number;
|
|
26
|
+
userInputLedger: import("../user-input-ledger.js").UserInputLedger | undefined;
|
|
26
27
|
webSearchProvider: "brave" | "tavily" | "searxng" | undefined;
|
|
27
28
|
approvalAskAudit: import("../approval-ask-audit-store.js").FileApprovalAskAuditStore | undefined;
|
|
28
29
|
centerRuntimeCapsResolver: ((principal: string | undefined) => Promise<import("@sema-agent/core").RuntimeCaps | undefined>) | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_MODEL_REF } from "../model-select.js";
|
|
2
|
-
import { probeSearchBackend } from "@sema-agent/core";
|
|
2
|
+
import { probeSearchBackend, uuidv7 } from "@sema-agent/core";
|
|
3
3
|
import { selectEnvironmentTool } from "../capabilities/select-environment-tool.js";
|
|
4
4
|
import { subagentSendUserFileExtraTools } from "../capabilities/send-user-file-tool.js";
|
|
5
5
|
import { parseCapEnv, parseNumOrFailNonNegative } from "../config.js";
|
|
@@ -16,6 +16,7 @@ import { explicitOperatorOk } from "../http/server.js";
|
|
|
16
16
|
import { selfOrchestrationDenial } from "../task-workflow.js";
|
|
17
17
|
import { centerEntitlementSourceWired } from "../runtime-caps-resolver.js";
|
|
18
18
|
import { reclaimOrphansAtBoot } from "../boot-reclaim.js";
|
|
19
|
+
import { createUserInputLedgerAtBoot, writerGoneEvidenceFor } from "../user-input-ledger.js";
|
|
19
20
|
import { createParkedReviveInheritedGate } from "./parked-revive-gate.js";
|
|
20
21
|
import { createParkedReviveSurface } from "../parked-revive-surface.js";
|
|
21
22
|
import { createWebFetchSummarizeLane } from "./webfetch-summarize-lane.js";
|
|
@@ -23,7 +24,7 @@ import { createRunnerDepsOnAsk } from "./runner-deps.js";
|
|
|
23
24
|
import { bindRateLimiter, bindRunStore } from "./late-binds.js";
|
|
24
25
|
import { buildDisplaySafeUrl } from "../trace/redact.js";
|
|
25
26
|
export async function runStage07(ctx) {
|
|
26
|
-
const { approvalExemptionStore, backend, backgroundAgentStore, brain, checkpointStore, config, configCenter, counterDegradeHook, durableEnabled, handslessSubRunner, localRoot, logger, memoryEngine, metrics, question, runner, runnerDeps, sendUserFileToolSpec, sessionEnvSelection, sessionStore, subRunner, subRunnerSessions, taskListLane, toolApproval } = ctx;
|
|
27
|
+
const { approvalExemptionStore, backend, backgroundAgentStore, brain, checkpointStore, config, configCenter, counterDegradeHook, durableEnabled, handslessSubRunner, instanceId, localRoot, logger, memoryEngine, metrics, question, runner, runnerDeps, sendUserFileToolSpec, sessionEnvSelection, sessionStore, subRunner, subRunnerSessions, taskListLane, toolApproval } = ctx;
|
|
27
28
|
const authorize = createAuthorizer(config, sessionStore);
|
|
28
29
|
const runStore = backend ? backend.run() : undefined;
|
|
29
30
|
bindRunStore(runStore);
|
|
@@ -50,6 +51,19 @@ export async function runStage07(ctx) {
|
|
|
50
51
|
if (gateRefusal !== undefined)
|
|
51
52
|
throw new Error(gateRefusal);
|
|
52
53
|
await reclaimOrphansAtBoot(runStore, checkpointStore, logger);
|
|
54
|
+
const userInputLedger = backend && runStore
|
|
55
|
+
? await (async () => {
|
|
56
|
+
const { ledger, converged } = await createUserInputLedgerAtBoot({
|
|
57
|
+
store: backend.userInputLedger(),
|
|
58
|
+
writer: instanceId,
|
|
59
|
+
evidence: writerGoneEvidenceFor(backend.kind, runStore),
|
|
60
|
+
newId: uuidv7,
|
|
61
|
+
});
|
|
62
|
+
if (converged > 0)
|
|
63
|
+
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" });
|
|
64
|
+
return ledger;
|
|
65
|
+
})()
|
|
66
|
+
: undefined;
|
|
53
67
|
const imageIndex = backend?.imageIndex ? backend.imageIndex() : undefined;
|
|
54
68
|
const selectEnvTool = config.selectEnvironmentTool && config.remoteExec?.provider === "k8s" && imageIndex
|
|
55
69
|
? selectEnvironmentTool({
|
|
@@ -156,6 +170,6 @@ export async function runStage07(ctx) {
|
|
|
156
170
|
const builtinScenarioNames = Object.keys(scenarioDetails);
|
|
157
171
|
configCenter.applyCenterScenarios({ scenarioDeps, scenarios, scenarioDetails, builtinScenarioNames });
|
|
158
172
|
logger.info("capabilities", { skills: skills.length, scenarios: Object.keys(scenarios), repoTools: Boolean(repoClient) });
|
|
159
|
-
return { ...ctx, approvalExemptionStore, approvalNonceStore, authorize, imageBakes, imageIndex, parkedReviveInheritedGate, parkedReviveSurface, rateLimiter, resumeAnchorStore, runStore, scenarioDetails, scenarios, selectEnvTool, taskLimitCaps, taskTimeoutSec, webSearchProvider: webSearchCfg?.provider };
|
|
173
|
+
return { ...ctx, approvalExemptionStore, approvalNonceStore, authorize, imageBakes, imageIndex, parkedReviveInheritedGate, parkedReviveSurface, rateLimiter, resumeAnchorStore, runStore, scenarioDetails, scenarios, selectEnvTool, taskLimitCaps, taskTimeoutSec, userInputLedger, webSearchProvider: webSearchCfg?.provider };
|
|
160
174
|
}
|
|
161
175
|
//# sourceMappingURL=stage-07-capability-layer.js.map
|
|
@@ -36,6 +36,7 @@ export declare function runStage08(ctx: Awaited<ReturnType<typeof runStage07>>):
|
|
|
36
36
|
maxTurns: number | undefined;
|
|
37
37
|
};
|
|
38
38
|
taskTimeoutSec: number;
|
|
39
|
+
userInputLedger: import("../user-input-ledger.js").UserInputLedger | undefined;
|
|
39
40
|
webSearchProvider: "brave" | "tavily" | "searxng" | undefined;
|
|
40
41
|
approvalAskAudit: import("../approval-ask-audit-store.js").FileApprovalAskAuditStore | undefined;
|
|
41
42
|
centerRuntimeCapsResolver: ((principal: string | undefined) => Promise<import("@sema-agent/core").RuntimeCaps | undefined>) | undefined;
|
|
@@ -5,12 +5,12 @@ import { startRetentionLane, RETENTION_LEASE_TTL_FACTOR } from "./retention-lane
|
|
|
5
5
|
import { createLimitSync } from "./limit-sync.js";
|
|
6
6
|
import { runDenySweep } from "./late-binds.js";
|
|
7
7
|
export function runStage08(ctx) {
|
|
8
|
-
const { approvalNonceStore, backend, backgroundAgentStore, ceilingVerdict, checkpointStore, config, configCenter, consolidationSeatWatch, costQuota, degradeRouteWatch, fileHistoryErasure, handslessRunner, handslessSubRunner, hookAgentRunner, imageBakes, instanceId, localRoot, logger, mailboxStore, metrics, permissionRuleStores, pricing, rateLimiter, retentionExecutor, retentionLaneStore, rosterStore, runStore, runner, sqlWorkflowRunStore, subRunner, taskAttachmentStore, toolApproval, toolResultStore, workflowJournalStore, workflowNotifyGate, workflowNotifyJournal, workflowRecoverOpts, worktreeReap } = ctx;
|
|
8
|
+
const { approvalNonceStore, backend, backgroundAgentStore, ceilingVerdict, checkpointStore, config, configCenter, consolidationSeatWatch, costQuota, degradeRouteWatch, fileHistoryErasure, handslessRunner, handslessSubRunner, hookAgentRunner, imageBakes, instanceId, localRoot, logger, mailboxStore, metrics, permissionRuleStores, pricing, rateLimiter, retentionExecutor, retentionLaneStore, rosterStore, runStore, runner, sqlWorkflowRunStore, subRunner, taskAttachmentStore, toolApproval, toolResultStore, userInputLedger, workflowJournalStore, workflowNotifyGate, workflowNotifyJournal, workflowRecoverOpts, worktreeReap } = ctx;
|
|
9
9
|
const reaper = startReapers({
|
|
10
10
|
config, logger, metrics, localRoot, backend, subRunner, runStore, checkpointStore,
|
|
11
11
|
rateLimiter, costQuota, toolResultStore, fileHistoryErasure, taskAttachmentStore, imageBakes, worktreeReap,
|
|
12
12
|
workflowNotifyGate, workflowRecoverOpts, workflowJournalStore, sqlWorkflowRunStore, workflowNotifyJournal, rosterStore,
|
|
13
|
-
backgroundAgentStore, mailboxStore, toolApproval, permissionRuleStores, approvalNonceStore,
|
|
13
|
+
backgroundAgentStore, mailboxStore, toolApproval, permissionRuleStores, approvalNonceStore, userInputLedger,
|
|
14
14
|
getRunDenySweep: () => runDenySweep,
|
|
15
15
|
});
|
|
16
16
|
const ttlMs = config.retentionSweep.intervalSec * 1000 * RETENTION_LEASE_TTL_FACTOR;
|
|
@@ -72,6 +72,7 @@ export declare function runStage09(ctx: Awaited<ReturnType<typeof runStage08>>):
|
|
|
72
72
|
maxTurns: number | undefined;
|
|
73
73
|
};
|
|
74
74
|
taskTimeoutSec: number;
|
|
75
|
+
userInputLedger: import("../user-input-ledger.js").UserInputLedger | undefined;
|
|
75
76
|
webSearchProvider: "brave" | "tavily" | "searxng" | undefined;
|
|
76
77
|
approvalAskAudit: import("../approval-ask-audit-store.js").FileApprovalAskAuditStore | undefined;
|
|
77
78
|
centerRuntimeCapsResolver: ((principal: string | undefined) => Promise<import("@sema-agent/core").RuntimeCaps | undefined>) | undefined;
|
|
@@ -72,6 +72,7 @@ export declare function runStage10(ctx: Awaited<ReturnType<typeof runStage09>>):
|
|
|
72
72
|
maxTurns: number | undefined;
|
|
73
73
|
};
|
|
74
74
|
taskTimeoutSec: number;
|
|
75
|
+
userInputLedger: import("../user-input-ledger.js").UserInputLedger | undefined;
|
|
75
76
|
webSearchProvider: "brave" | "tavily" | "searxng" | undefined;
|
|
76
77
|
approvalAskAudit: import("../approval-ask-audit-store.js").FileApprovalAskAuditStore | undefined;
|
|
77
78
|
centerRuntimeCapsResolver: ((principal: string | undefined) => Promise<import("@sema-agent/core").RuntimeCaps | undefined>) | undefined;
|
|
@@ -26,7 +26,7 @@ import { bindServerLateSeats } from "./late-binds.js";
|
|
|
26
26
|
import { serviceVersion } from "../service-version.js";
|
|
27
27
|
import { buildDisplaySafeUrl } from "../trace/redact.js";
|
|
28
28
|
export async function runStage10(ctx) {
|
|
29
|
-
const { approvalAskAudit, approvalExemptionStore, approvalNonceStore, authorize, backend, backgroundAgentStore, brain, breakerState, centerRuntimeCapsResolver, checkpointStore, parkCommits, config, configCenter, consolidationValve, costQuota, deploymentHooks, deviceLane, drainState, durableEnabled, elicitation, fenceSessionOwner, noteSessionIncarnation, fileHistoryStore, fleetBus, fleetLease, fleetUsage, governanceSeams, handslessRunner, hookAgent, hookLlm, hookWakeBus, imageBakes, imageIndex, instanceId, instrumentDegenerate, leaderEndpoint, localRoot, logger, lspManager, mcpRevocations, memoryBundleFaces, memoryComplianceFaces, memoryConsolidationFaces, memoryEngine, memoryExportBackend, memoryOptOutGrantStore, memoryOriginFaces, memoryPosture, memorySyncCursors, metrics, modelUsageTracker, orgMemoryAdmission, otelExporter, outcomeSink, ownerAware, parkedReviveInheritedGate, parkedReviveSurface, perSessionCwd, perTaskImage, planCacheProbe, pricing, principalCaps, promptManifestTracker, purgeSession, question, rateLimiter, reaper, registryJwtVerifier, resumeAnchorStore, retentionLaneStarted, retentionLaneStore, ruleConsent, runStore, runner, runnerDeps, runtimeCapsPeekResolver, scenarioDetails, scenarios, selectEnvTool, sendFileLedger, sendUserFileEmitter, sendUserFileToolSpec, sessionAudit, sessionEnvSelection, sessionMemoryStatusFace, sessionPolicyStore, sessionTitler, sessionWatchRegistry, setSessionCwd, setSessionInheritEnv, setSessionShellEnv, sharedMemoryStore, sideQueryAccounting, sqlEngineFacts, sqlWorkflowRunStore, staticWiring, storePosture, subRunner, subagentSteerRegistry, taskAttachmentStore, taskLimitCaps, taskTimeoutSec, toolApproval, toolResultStore, usageWindowStore, webSearchProvider, workflowAgentRegistry, workflowAgentSessionIndex, workflowCompletionInbox, workflowJournalStore, workflowModelAllowlistSnapshot, workflowNotifyGate, workflowNotifyJournal, workflowRecoverOpts, workflowRunStore, workflowsCapable } = ctx;
|
|
29
|
+
const { approvalAskAudit, approvalExemptionStore, approvalNonceStore, authorize, backend, backgroundAgentStore, brain, breakerState, centerRuntimeCapsResolver, checkpointStore, parkCommits, config, configCenter, consolidationValve, costQuota, deploymentHooks, deviceLane, drainState, durableEnabled, elicitation, fenceSessionOwner, noteSessionIncarnation, fileHistoryStore, fleetBus, fleetLease, fleetUsage, governanceSeams, handslessRunner, hookAgent, hookLlm, hookWakeBus, imageBakes, imageIndex, instanceId, instrumentDegenerate, leaderEndpoint, localRoot, logger, lspManager, mcpRevocations, memoryBundleFaces, memoryComplianceFaces, memoryConsolidationFaces, memoryEngine, memoryExportBackend, memoryOptOutGrantStore, memoryOriginFaces, memoryPosture, memorySyncCursors, metrics, modelUsageTracker, orgMemoryAdmission, otelExporter, outcomeSink, ownerAware, parkedReviveInheritedGate, parkedReviveSurface, perSessionCwd, perTaskImage, planCacheProbe, pricing, principalCaps, promptManifestTracker, purgeSession, question, rateLimiter, reaper, registryJwtVerifier, resumeAnchorStore, retentionLaneStarted, retentionLaneStore, ruleConsent, runStore, runner, runnerDeps, runtimeCapsPeekResolver, scenarioDetails, scenarios, selectEnvTool, sendFileLedger, sendUserFileEmitter, sendUserFileToolSpec, sessionAudit, sessionEnvSelection, sessionMemoryStatusFace, sessionPolicyStore, sessionTitler, sessionWatchRegistry, setSessionCwd, setSessionInheritEnv, setSessionShellEnv, sharedMemoryStore, sideQueryAccounting, sqlEngineFacts, sqlWorkflowRunStore, staticWiring, storePosture, subRunner, subagentSteerRegistry, taskAttachmentStore, taskLimitCaps, taskTimeoutSec, toolApproval, toolResultStore, usageWindowStore, userInputLedger, webSearchProvider, workflowAgentRegistry, workflowAgentSessionIndex, workflowCompletionInbox, workflowJournalStore, workflowModelAllowlistSnapshot, workflowNotifyGate, workflowNotifyJournal, workflowRecoverOpts, workflowRunStore, workflowsCapable } = ctx;
|
|
30
30
|
const stores = {
|
|
31
31
|
runStore,
|
|
32
32
|
resumeAnchorStore: resumeAnchorStore ? resumeAnchorStore : undefined,
|
|
@@ -48,6 +48,7 @@ export async function runStage10(ctx) {
|
|
|
48
48
|
imageBakes,
|
|
49
49
|
outcomeSink: outcomeSink ? outcomeSink : undefined,
|
|
50
50
|
sendFileLedger: sendFileLedger ? sendFileLedger : undefined,
|
|
51
|
+
userInputLedger,
|
|
51
52
|
backend: backend ? backend : undefined,
|
|
52
53
|
};
|
|
53
54
|
let resolveFleetRecovery;
|
|
@@ -246,8 +246,9 @@ export declare function centerScenarios(deps: ScenarioDeps, specs: CenterScenari
|
|
|
246
246
|
};
|
|
247
247
|
/**
|
|
248
248
|
* Personalization seam: merge the caller's own skills AFTER the scenario's, with
|
|
249
|
-
* SCENARIO-WINS on a name clash — the
|
|
250
|
-
*
|
|
249
|
+
* SCENARIO-WINS on a name clash — the scenario / center skills own the name (they are the deployment's baseline
|
|
250
|
+
* wording, not an enforcement face: permissions / write gates / hooks do not ride on skills, and a caller may
|
|
251
|
+
* unload the whole set with `disableSkills`, S-946); user content never shadows them. Duplicate names within the user list keep the first. Clashes are logged for audit
|
|
251
252
|
* (silent drops would make "my skill didn't fire" undebuggable). Input is already shape/size-validated
|
|
252
253
|
* by the HTTP layer (validateUserSkills); this stays pure merge policy.
|
|
253
254
|
*/
|
package/dist/config-catalog.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { CROSS_SESSION_INBOUND_SETTINGS, CROSS_SESSION_DIALOG_EXPIRY_VALUES
|
|
1
|
+
import { CROSS_SESSION_INBOUND_SETTINGS, CROSS_SESSION_DIALOG_EXPIRY_VALUES } from "@sema-agent/core";
|
|
2
2
|
import { CENTER_CREDENTIAL_ENV, DOMAIN_SCHEMAS } from "@sema-agent/settings-schema";
|
|
3
3
|
import { CENTER_CREDENTIAL_RENEW_LEAD_DEFAULT_MS, CENTER_CREDENTIAL_RENEW_LEAD_MAX_MS, CENTER_CREDENTIAL_RENEW_LEAD_MIN_MS } from "./center-credential-renewer.js";
|
|
4
4
|
import { THINKING_FORMATS } from "./model-compat.js";
|
|
5
5
|
import { AUTO_MODE_CLASSIFIER_TIMEOUT_BOUNDS, CONFIG_PROVIDER_WORDS, DB_BACKEND_WORDS, DRAIN_SECOND_SIGNAL_MIN_GAP_BOUNDS, DRAIN_SECOND_SIGNAL_MIN_GAP_DEFAULT_MS, FIRST_BYTE_TIMEOUT_BOUNDS, RESILIENCE_DEFAULTS, TASK_WRITE_FACE_ESCALATIONS } from "./config-types.js";
|
|
6
6
|
import { webSearchProviderFromEnv, WEB_SEARCH_PROVIDERS } from "./plugins/web-search.js";
|
|
7
|
-
import { UNATTENDED_PERMISSION_MODE_DEFAULT } from "./unattended-permission-mode.js";
|
|
8
7
|
import { AUTONOMY_MODES } from "./runtime-governance.js";
|
|
9
8
|
import { REMOTE_EXEC_PROVIDER_WORDS } from "./execution-lane-caps.js";
|
|
10
9
|
import { MODEL_PROVIDER_WORDS } from "./model-provider.js";
|
|
@@ -245,7 +244,7 @@ export const CONFIG_CATALOG = [
|
|
|
245
244
|
r("MEMORY_SCOPE", "memory", "string", "单用户部署的记忆 scope 名", { derivedDefaultNote: "缺席:引擎开 ∧ 单用户 ⇒ local;其余 ⇒ 缺席(记忆暗)", configKey: "memoryScope" }),
|
|
246
245
|
r("MEMORY_SYNC_MAX_PULL_ENTRIES", "memory", "number", "TOC 同步单轮 pull 条数帽(设了必须 ≥1 整数)", { derivedDefaultNote: "缺席 ⇒ 键缺席,core 默认" }),
|
|
247
246
|
r("MEMORY_SYNC_MAX_PUSH_ENTRIES", "memory", "number", "TOC 同步单轮 push 条数帽(设了必须 ≥1 整数)", { derivedDefaultNote: "缺席 ⇒ 键缺席,core 默认" }),
|
|
248
|
-
r("MEMORY_SYNC_SCOPE", "memory", "string", "TOC 同步 scope 覆写", { derivedDefaultNote: "缺席 ⇒
|
|
247
|
+
r("MEMORY_SYNC_SCOPE", "memory", "string", "TOC 同步 scope 覆写", { derivedDefaultNote: "缺席 ⇒ = MEMORY_SCOPE,仅当它已是 typed 键;非 typed 键拒启(S-964)" }),
|
|
249
248
|
r("MEMORY_SYNC_TOKEN", "memory", "secret", "TOC 同步中心面的 Bearer(URL 设了它必须在,半配拒启)", { danger: SEC }),
|
|
250
249
|
r("MEMORY_SYNC_URL", "memory", "url", "TOC 同步中心地址(设了=开;file 记忆形专用,DB 后端配了拒启;同步只覆盖一层 ⇒ 单用户任务不按项目键控、写家落全局层 MEMORY_SCOPE(S-512 让位,启动通知 `memory_project_scope_yields_to_sync`))"),
|
|
251
250
|
r("METRICS_TOKEN", "observability", "secret", "/metrics 只读令牌", { danger: SEC }),
|
|
@@ -454,7 +453,6 @@ export const CONFIG_CATALOG = [
|
|
|
454
453
|
r("TRACE_THINKING", "observability", "boolean", "思考轨迹入 durable 事件日志(敏感部署可关;落盘前脱敏)", { staticDefault: "true", danger: DATA, configKey: "traceThinking" }),
|
|
455
454
|
r("TRACE_TOKEN", "observability", "secret", "Task Trace API 只读令牌(fleet 拉轨迹,不授任务/配置权)", { danger: SEC }),
|
|
456
455
|
r("UNATTENDED_APPROVAL_POLICY", "approval", "enum", "无人能答的治理 ask 终局(park=durable 等人;deny=当场拒 —— 自声明无人值守)", { enumValues: ["park", "deny"], staticDefault: "park", danger: SEC, configKey: "unattendedApprovalPolicy" }),
|
|
457
|
-
r("UNATTENDED_PERMISSION_MODE", "approval", "enum", "无人值守腿(leader worker / leader 修复腿 / run-local:本仓自铸 spec、无调用方可表态、无审批席)的权限模式;写面恒 roots(不随 bypassPermissions 开放);词表外拒启", { enumValues: [...PERMISSION_MODES], staticDefault: UNATTENDED_PERMISSION_MODE_DEFAULT, danger: SEC, configKey: "unattendedPermissionMode" }),
|
|
458
456
|
r("UNREACHED_ASK_TTL_MS", "approval", "number", "零活流铸造的 ask 悬挂窗(ms;[60s,24h] 拒启带界)", { staticDefault: "3600000" }),
|
|
459
457
|
r("USAGE_WINDOWS", "orchestration", "opaque", "部署级治理窗(JSON 数组;滑动窗内跨任务 token/$ 预算,key=principal)", { danger: BILL }),
|
|
460
458
|
r("WEB_SEARCH_API_KEY", "orchestration", "secret", "web search 后端 API 凭据(brave/tavily)", { danger: [...SEC, ...BILL] }),
|
package/dist/config-provider.js
CHANGED
|
@@ -125,6 +125,7 @@ export function mapToServiceEffective(eff, version) {
|
|
|
125
125
|
...(m.cost !== undefined ? { cost: m.cost } : {}),
|
|
126
126
|
...(m.extraBody !== undefined ? { extraBody: m.extraBody } : {}),
|
|
127
127
|
...(m.compat !== undefined ? { compat: m.compat } : {}),
|
|
128
|
+
...(m.headers !== undefined ? { headers: m.headers } : {}),
|
|
128
129
|
...(m.promptGuidance !== undefined ? { promptGuidance: m.promptGuidance } : {}),
|
|
129
130
|
enabled: m.enabled,
|
|
130
131
|
})),
|
package/dist/config-types.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type { ReadFaceSource } from "./read-face-posture.js";
|
|
|
9
9
|
import type { PostureSource } from "./posture-source.js";
|
|
10
10
|
import type { SealedCustodyPoison } from "./key-resolver.js";
|
|
11
11
|
import type { ModelEntryRefusal } from "./model-entry-refusal.js";
|
|
12
|
-
import type {
|
|
12
|
+
import type { A2aServerSpec, CompliancePosture, CrossSessionDialogExpiry, CrossSessionInboundSetting, FileHistoryRetentionPolicy, LockedKey, McpServerSpec, Model, ModelRoles, RetentionPolicy, ShellGateDoctrine, WriteProtectedEntry } from "@sema-agent/core";
|
|
13
13
|
import type { ApprovalHmacKey, PrincipalJwtKey } from "./auth-keys.js";
|
|
14
14
|
import type { ElicitationThrottle } from "./elicitation.js";
|
|
15
15
|
import type { QuestionThrottle } from "./question.js";
|
|
@@ -680,8 +680,9 @@ export interface ServiceConfigFlat {
|
|
|
680
680
|
memoryPersistenceCapable?: boolean;
|
|
681
681
|
/** 142-S2.5-W1: TOC 同步 client 腿 —— file memory 形态把本地记忆盘与中心(DB 权威,
|
|
682
682
|
* POST /v1/memory/sync/:scope)做一轮一 RTT 双向同步。env 三键:`MEMORY_SYNC_URL`(设了=开;缺省
|
|
683
|
-
* undefined=纯本地现状零变化)/`MEMORY_SYNC_TOKEN`(Bearer)/`MEMORY_SYNC_SCOPE`(
|
|
684
|
-
*
|
|
683
|
+
* undefined=纯本地现状零变化)/`MEMORY_SYNC_TOKEN`(Bearer)/`MEMORY_SYNC_SCOPE`(可选,缺省 =
|
|
684
|
+
* memoryScope 本身**仅当它已是 v2 typed key**;非 typed 键 ⇒ 拒启,S-964 —— 旧 formatUserScope 派生臂铸出的是本部署
|
|
685
|
+
* 从不写的层,见 loadConfig)。半配置 fail-loud
|
|
685
686
|
* (memoryEngineBackend 同款姿势);DB backend(pg/tidb)配了这些键=boot throw(中心侧自己就是
|
|
686
687
|
* 同步权威,不该再跑 client 腿)。 */
|
|
687
688
|
memorySync?: {
|
|
@@ -1920,13 +1921,6 @@ export interface ServiceConfigFlat {
|
|
|
1920
1921
|
* 把批关掉(同腿后续的卡人批不动)、把兄弟连坐成 VOID(裸 `false` = 人拒)。
|
|
1921
1922
|
*/
|
|
1922
1923
|
unattendedApprovalPolicy: UnattendedApprovalPolicy;
|
|
1923
|
-
/**
|
|
1924
|
-
* S-877 候裁 15 → B(`UNATTENDED_PERMISSION_MODE`)—— 本仓**自铸** spec、无调用方可表态、无审批席的腿(leader worker / leader 修复腿 /
|
|
1925
|
-
* run-local)的 `TaskSpec.permissionMode`。闭集 = core `PERMISSION_MODES`,缺省 `bypassPermissions`(写门 / 形状层 = 7.105.0;写保护经 `createUnattendedWriteProtectionPolicy` 从问改拒;其余六类释放 = 宽化,候裁 18 D),坏值拒启。
|
|
1926
|
-
* 规则 / 三问 / 写面 / 射程外**一处成文** = `src/unattended-permission-mode.ts` 模块头注;唯一读函数 `unattendedPermissionMode(config)`。
|
|
1927
|
-
* 纯部署级:不读任何客户端表态、不参与托管姿态(这些腿不是请求)。
|
|
1928
|
-
*/
|
|
1929
|
-
unattendedPermissionMode: PermissionMode;
|
|
1930
1924
|
/** [ref]① (clay A 案 = workflow 权限全面 CC parity): workflow 子 agent 的默认权限基线与主 LLM 同权(base `{}`)。
|
|
1931
1925
|
* 安全论证:主 LLM 与子 agent 同 root 同信任域,主 LLM 本就能写这棵树([ref] ask 门照管),单独钳子 agent 的
|
|
1932
1926
|
* 安全增益≈0(只防绕路不防直路的门不是边界);实测产品代价=[ref]A 死锁。`WORKFLOW_AGENTS_READONLY=true` =
|
|
@@ -2113,7 +2107,7 @@ export type ServiceStoreConfig = Pick<ServiceConfigFlat, "sessionBackend" | "ses
|
|
|
2113
2107
|
export type ServiceModelPlaneConfig = Pick<ServiceConfigFlat, "gatewayBaseUrl" | "gatewayApiKey" | "gatewayFallbackUrls" | "gatewayMaxRetries" | "anthropic" | "resilience" | "model" | "envModel" | "models" | "modelApiKeyEnv" | "modelApiKeys" | "modelRefusals" | "modelQuotaWeights" | "tiers" | "projects" | "roles" | "atModelAllowlist" | "cascadeLadder" | "degrade">;
|
|
2114
2108
|
/** 组:approval(审批 / HITL 门)。`directDoorActive` 无 env 解析腿(装配层三域合取的产物),但语义上
|
|
2115
2109
|
* 就是本组的门状态,故进组;`parseApprovalDomain` 的返回类型相应是 `Omit<…, "directDoorActive">`。 */
|
|
2116
|
-
export type ServiceApprovalConfig = Pick<ServiceConfigFlat, "approvalRequire" | "approvalDeny" | "approvalTimeoutSec" | "approvalAutoBudget" | "approvalNeverAuto" | "approvalHmacKeys" | "durableApproval" | "durableApprovalSource" | "streamAskWindowMsSource" | "directApprovalDoor" | "directDoorActive" | "resourceSuspend" | "resourceSuspendTtlSec" | "resourceSuspendTotalTokens" | "resourceSuspendTotalBudgetUsd" | "resourceSuspendMaxSlices" | "askQuestionEnabled" | "questionThrottle" | "toolApprovalEnabled" | "permissionRulesEnabled" | "permissionRulesEnabledExplicit" | "streamAskWindowMarginMs" | "streamApproval" | "unattendedApprovalPolicy" | "
|
|
2110
|
+
export type ServiceApprovalConfig = Pick<ServiceConfigFlat, "approvalRequire" | "approvalDeny" | "approvalTimeoutSec" | "approvalAutoBudget" | "approvalNeverAuto" | "approvalHmacKeys" | "durableApproval" | "durableApprovalSource" | "streamAskWindowMsSource" | "directApprovalDoor" | "directDoorActive" | "resourceSuspend" | "resourceSuspendTtlSec" | "resourceSuspendTotalTokens" | "resourceSuspendTotalBudgetUsd" | "resourceSuspendMaxSlices" | "askQuestionEnabled" | "questionThrottle" | "toolApprovalEnabled" | "permissionRulesEnabled" | "permissionRulesEnabledExplicit" | "streamAskWindowMarginMs" | "streamApproval" | "unattendedApprovalPolicy" | "mcpElicitation" | "sensitiveWritePatterns" | "writeProtectedPaths" | "manualModeShellGate" | "permissionsDisableAutoMode" | "autoModeClassifierFallback" | "autoModeClassifierTimeoutMs" | "crossSessionInbound" | "crossSessionDialogExpiry">;
|
|
2117
2111
|
/** 组:memory(记忆面 + TOC 同步腿)。 */
|
|
2118
2112
|
export type ServiceMemoryConfig = Pick<ServiceConfigFlat, "memoryEngineEnabled" | "memoryEngineDir" | "memoryEngineRemoteLaneAllowed" | "memoryEngineBackend" | "memoryScope" | "memoryPersistenceCapable" | "memorySync" | "memoryEmbedder" | "memoryOrgAdmissionMode" | "memoryDelegationEvidence" | "memoryProvenance" | "memoryCapturePolicy" | "memoryConsolidationDriver" | "memoryOrgDirectoryJson" | "memoryOrgGrantTtlMs" | "memoryOrgUnavailableBackoffMs" | "projectMemoryEnabled" | "syncImportLeaseStaleSec">;
|
|
2119
2113
|
/** 组:auth(鉴权 / 身份 / 治理棒)。`commandPolicy` 只有 sema-registry 腿(无 env 标量形),故 env 解析
|
package/dist/config.js
CHANGED
|
@@ -3,11 +3,11 @@ import { DEFAULT_MODEL_REF } from "./model-select.js";
|
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { BUILTIN_COMPLIANCE_DENIES, COMPLIANCE_CAPABILITIES, CROSS_SESSION_INBOUND_SETTINGS, CROSS_SESSION_DIALOG_EXPIRY_VALUES, compileReadDeny, resolveReadDenyBuiltins, CODE_AGENT_PROMPT,
|
|
6
|
+
import { BUILTIN_COMPLIANCE_DENIES, COMPLIANCE_CAPABILITIES, CROSS_SESSION_INBOUND_SETTINGS, CROSS_SESSION_DIALOG_EXPIRY_VALUES, compileReadDeny, resolveReadDenyBuiltins, CODE_AGENT_PROMPT, isModelPriced, PROTOCOL_TABLE, protocolOf, RECOMMENDED_SENSITIVE_PATTERNS, RETIRED_TOOL_NAMES, resolveFileHistoryRetention, resolveLockedKeys, validatePermissionRules, WRITE_PROTECTED_DEFAULT_TABLE, resolveWriteProtectedTable, parseRuleText } from "@sema-agent/core";
|
|
7
7
|
import { ROSTER_PRIMARY_ROLES, ROSTER_CHEAP_ROLES, CENTER_CREDENTIAL_ENV } from "@sema-agent/settings-schema";
|
|
8
8
|
import { parseApprovalHmacKeys, parsePrincipalJwks } from "./auth-keys.js";
|
|
9
9
|
import { DEFAULT_ELICITATION_THROTTLE } from "./elicitation.js";
|
|
10
|
-
import { isV2ScopeKey, memoryReplicationCoverage } from "./memory-scope.js";
|
|
10
|
+
import { isV2ScopeKey, memoryReplicationCoverage, replicationCovers } from "./memory-scope.js";
|
|
11
11
|
import { DEFAULT_QUESTION_THROTTLE } from "./question.js";
|
|
12
12
|
import { GIT_API_KINDS, isGitApiKind } from "./git-api-kind.js";
|
|
13
13
|
import { CONFIG_PROVIDER_WORDS, DB_BACKEND_WORDS, RETENTION_MODES, MEMORY_CONSOLIDATION_MIN_INTERVAL_SEC, RESILIENCE_DEFAULTS, TASK_WRITE_FACE_ESCALATIONS, MAX_TIMER_DELAY_MS, AUTO_MODE_CLASSIFIER_TIMEOUT_BOUNDS, DRAIN_GRACE_FLOOR_MS, DRAIN_SECOND_SIGNAL_MIN_GAP_BOUNDS, DRAIN_SECOND_SIGNAL_MIN_GAP_DEFAULT_MS, FIRST_BYTE_TIMEOUT_BOUNDS } from "./config-types.js";
|
|
@@ -27,7 +27,6 @@ import { modelRouteEndpointRefusal } from "./model-route-endpoint.js";
|
|
|
27
27
|
import { buildDisplaySafeUrl, redactSecrets } from "./trace/redact.js";
|
|
28
28
|
import { allowlistedEnv } from "./server-secret-env.js";
|
|
29
29
|
import { ENV_NAME_ALLOWLIST_KNOBS, ENV_NAME_ALLOWLIST_KNOB_NAMES, describeAllowlistPostures } from "./env-name-allowlist-knobs.js";
|
|
30
|
-
import { parseUnattendedPermissionMode } from "./unattended-permission-mode.js";
|
|
31
30
|
export { RETENTION_MODES, MEMORY_CONSOLIDATION_MIN_INTERVAL_SEC } from "./config-types.js";
|
|
32
31
|
function csv(name) {
|
|
33
32
|
return (process.env[name] ?? "")
|
|
@@ -135,6 +134,7 @@ export const RETIRED_ENVS = [
|
|
|
135
134
|
["CONFIG_LKG_DISABLED", "CONFIG_LKG_ENABLED", "replaced", "negative-name alias retired in server 3.0.0 — unset it; the polarity is inverted: CONFIG_LKG_DISABLED=true is CONFIG_LKG_ENABLED=false (the positive name defaults on)"],
|
|
136
135
|
["HOST_BG_DISABLED", "HOST_BG_ENABLED", "replaced", "negative-name alias retired in server 3.0.0 — unset it; the polarity is inverted: HOST_BG_DISABLED=true is HOST_BG_ENABLED=false (the positive name defaults on)"],
|
|
137
136
|
["HOST_EXEC_SPOOL_DISABLED", "HOST_EXEC_SPOOL_ENABLED", "replaced", "negative-name alias retired in server 3.0.0 — unset it; the polarity is inverted: HOST_EXEC_SPOOL_DISABLED=true is HOST_EXEC_SPOOL_ENABLED=false (the positive name defaults on)"],
|
|
137
|
+
["UNATTENDED_PERMISSION_MODE", "since server 7.109.0 the unattended legs (leader workers and their repair legs, run-local, and their durable resumes) always run permissionMode \"default\" with an approver that answers by ask class: a machine answers only \"ordinary\" asks, and every other class goes to the leg's approver seat (run-local's terminal prompt) or parks / is refused — there is no mode to choose", "removed"],
|
|
138
138
|
];
|
|
139
139
|
for (const row of RETIRED_ENVS)
|
|
140
140
|
Object.freeze(row);
|
|
@@ -1327,8 +1327,6 @@ function unattendedApprovalPolicyEnv() {
|
|
|
1327
1327
|
function parseApprovalDomain(ctx) {
|
|
1328
1328
|
const { postureOn, singleUserTurnkey, infraReady } = ctx;
|
|
1329
1329
|
const unattendedPolicy = unattendedApprovalPolicyEnv();
|
|
1330
|
-
const unattendedMode = parseUnattendedPermissionMode(process.env.UNATTENDED_PERMISSION_MODE);
|
|
1331
|
-
CONFIG_NOTICES.push({ level: "info", event: "unattended_permission_mode", fields: { value: unattendedMode.value, source: unattendedMode.source } });
|
|
1332
1330
|
const streamAskWindowMsSource = postureSourceOfNumEnv(process.env.STREAM_ASK_WINDOW_MS, singleUserTurnkey);
|
|
1333
1331
|
const toolApprovalEnabled = postureOn("TOOL_APPROVAL_ENABLED");
|
|
1334
1332
|
let streamAskWindowMsEffectiveSource = streamAskWindowMsSource;
|
|
@@ -1429,7 +1427,6 @@ function parseApprovalDomain(ctx) {
|
|
|
1429
1427
|
streamAskWindowMsSource: streamAskWindowMsEffectiveSource,
|
|
1430
1428
|
durableApprovalSource: postureSourceOfKnob("DURABLE_APPROVAL"),
|
|
1431
1429
|
unattendedApprovalPolicy: unattendedPolicy,
|
|
1432
|
-
unattendedPermissionMode: unattendedMode.value,
|
|
1433
1430
|
approvalTimeoutSec: numEnv("APPROVAL_TIMEOUT_SEC", "0"),
|
|
1434
1431
|
};
|
|
1435
1432
|
}
|
|
@@ -1669,9 +1666,14 @@ function parseMemoryDomain(ctx) {
|
|
|
1669
1666
|
if (memorySyncToken === undefined) {
|
|
1670
1667
|
throw new Error("MEMORY_SYNC_URL is set but MEMORY_SYNC_TOKEN is not — refusing to start half-configured (the central sync face requires a bearer token)");
|
|
1671
1668
|
}
|
|
1672
|
-
|
|
1669
|
+
if (memorySyncScopeRaw === undefined && memoryScope !== undefined && !isV2ScopeKey(memoryScope)) {
|
|
1670
|
+
throw new Error(`MEMORY_SYNC_URL is set but MEMORY_SYNC_SCOPE is not set and MEMORY_SCOPE (${JSON.stringify(memoryScope)}) is not a typed scope key — the sync leg replicates exactly ONE scope by name ` +
|
|
1671
|
+
"(core syncMemoryScope takes the entries whose scope === the sync scope and POSTs them under that same name), so deriving `user:<MEMORY_SCOPE>` would name a scope this deployment never writes and nothing would ever be synced (S-964). " +
|
|
1672
|
+
"Either set MEMORY_SYNC_SCOPE to the scope to replicate, or set MEMORY_SCOPE to the typed key the center expects (e.g. user:<tenant>) so the sync scope defaults to the same name.");
|
|
1673
|
+
}
|
|
1674
|
+
const scope = memorySyncScopeRaw ?? memoryScope;
|
|
1673
1675
|
if (scope === undefined) {
|
|
1674
|
-
throw new Error("MEMORY_SYNC_URL is set but no sync scope is derivable (memory engine off or multi-tenant without an explicit scope) — set MEMORY_SYNC_SCOPE, or run the single-user file memory engine
|
|
1676
|
+
throw new Error("MEMORY_SYNC_URL is set but no sync scope is derivable (memory engine off or multi-tenant without an explicit scope) — set MEMORY_SYNC_SCOPE, or run the single-user file memory engine with a typed MEMORY_SCOPE (e.g. user:<tenant>) so it provides one");
|
|
1675
1677
|
}
|
|
1676
1678
|
memorySync = {
|
|
1677
1679
|
url: memorySyncUrl,
|
|
@@ -1683,15 +1685,22 @@ function parseMemoryDomain(ctx) {
|
|
|
1683
1685
|
}
|
|
1684
1686
|
const replication = memoryReplicationCoverage(memorySync !== undefined ? { memorySync } : {});
|
|
1685
1687
|
if (replication.kind === "scopes" && memoryEngineEnabled && !requirePrincipal && memoryScope !== undefined) {
|
|
1688
|
+
const YIELD_HINT = {
|
|
1689
|
+
in: "memory sync (MEMORY_SYNC_*) replicates only the scope(s) listed in replicatedScopes — the per-project memory layer (S-512, repo:<key>) is not replicated, " +
|
|
1690
|
+
"so sessions do NOT write project-keyed memory here: new memory lands in the global layer (writeScope = MEMORY_SCOPE), which IS replicated, and every " +
|
|
1691
|
+
"project reads it. Project-layer replication is a separate change; unset MEMORY_SYNC_URL to get per-project memory without sync.",
|
|
1692
|
+
out: "memory sync (MEMORY_SYNC_*) replicates only the scope(s) listed in replicatedScopes — the per-project memory layer (S-512, repo:<key>) is not replicated, " +
|
|
1693
|
+
"so sessions do NOT write project-keyed memory here: new memory lands in the global layer (writeScope = MEMORY_SCOPE), every project reads it, " +
|
|
1694
|
+
"and that write scope is not among the replicated scopes either — NONE of the memory this deployment writes is synced. " +
|
|
1695
|
+
"Point MEMORY_SYNC_SCOPE at the write scope (sync replicates one scope), or unset MEMORY_SYNC_URL to stop expecting sync.",
|
|
1696
|
+
};
|
|
1686
1697
|
CONFIG_NOTICES.push({
|
|
1687
1698
|
level: "warn",
|
|
1688
1699
|
event: "memory_project_scope_yields_to_sync",
|
|
1689
1700
|
fields: {
|
|
1690
1701
|
replicatedScopes: replication.scopes.join(","),
|
|
1691
1702
|
writeScope: memoryScope,
|
|
1692
|
-
hint:
|
|
1693
|
-
"so sessions do NOT write project-keyed memory here: new memory lands in the global layer (MEMORY_SCOPE), the same as 7.97.0, and every " +
|
|
1694
|
-
"project reads it. Project-layer replication is a separate change; unset MEMORY_SYNC_URL to get per-project memory without sync.",
|
|
1703
|
+
hint: YIELD_HINT[replicationCovers(replication, memoryScope) ? "in" : "out"],
|
|
1695
1704
|
},
|
|
1696
1705
|
});
|
|
1697
1706
|
}
|
|
@@ -2299,7 +2308,7 @@ const MODEL_PLANE_GROUP_KEYS = [
|
|
|
2299
2308
|
const APPROVAL_GROUP_KEYS = [
|
|
2300
2309
|
"approvalRequire", "approvalDeny", "approvalTimeoutSec", "approvalAutoBudget", "approvalNeverAuto",
|
|
2301
2310
|
"approvalHmacKeys", "durableApproval", "durableApprovalSource", "streamAskWindowMsSource", "directApprovalDoor", "directDoorActive", "resourceSuspend",
|
|
2302
|
-
"resourceSuspendTtlSec", "resourceSuspendTotalTokens", "resourceSuspendTotalBudgetUsd", "resourceSuspendMaxSlices", "askQuestionEnabled", "questionThrottle", "toolApprovalEnabled", "permissionRulesEnabled", "permissionRulesEnabledExplicit", "streamAskWindowMarginMs", "streamApproval", "unattendedApprovalPolicy", "
|
|
2311
|
+
"resourceSuspendTtlSec", "resourceSuspendTotalTokens", "resourceSuspendTotalBudgetUsd", "resourceSuspendMaxSlices", "askQuestionEnabled", "questionThrottle", "toolApprovalEnabled", "permissionRulesEnabled", "permissionRulesEnabledExplicit", "streamAskWindowMarginMs", "streamApproval", "unattendedApprovalPolicy", "mcpElicitation",
|
|
2303
2312
|
"sensitiveWritePatterns", "writeProtectedPaths", "manualModeShellGate", "permissionsDisableAutoMode", "autoModeClassifierFallback", "autoModeClassifierTimeoutMs", "crossSessionInbound", "crossSessionDialogExpiry",
|
|
2304
2313
|
];
|
|
2305
2314
|
const MEMORY_GROUP_KEYS = [
|
|
@@ -243,8 +243,14 @@ export declare function buildOnlySensitiveBaselineWarning(config: Pick<Deploymen
|
|
|
243
243
|
* `applyRuntimeGovernance` 的 governance 实参预铸([ref] 件一)。
|
|
244
244
|
*
|
|
245
245
|
* 键存在性 profile 逐字保持消费腿原样:`autonomy`/`commandPolicy` 恒在场(值可为 `undefined`),
|
|
246
|
-
* `manualModeShellGate`/`
|
|
247
|
-
*
|
|
246
|
+
* `manualModeShellGate`/`sensitivePathLayers` 按在场性条件展开 —— `applyRuntimeGovernance` 对缺席与空的判读等价,
|
|
247
|
+
* 但 profile 是折叠面的可观测字节,搬家不许顺手改。
|
|
248
|
+
*
|
|
249
|
+
* 🔴 **S-958(core #1266 7.39.0)—— 守卫集交叶,不交折叠**:修前这里铸一只预折的 `sensitivePathPolicy`
|
|
250
|
+
* (`combinePolicies(真身层, 誊本门)`,沙箱形再套一层两形的折叠),治理层随后在**整个治理折叠的输出上**展开盖部署出身。
|
|
251
|
+
* 现在治理层逐叶盖位、只折一次(`runtime-governance.ts` `applyRuntimeGovernance` 顶注末段),所以本口交出的是叶的列表:
|
|
252
|
+
* 本口不知道出身这件事,也不再有自己的折叠点。叶的顺序 = 修前折叠的顺序(真身层 → 词法层 → 誊本门),deny 优先 / 首问 / 成员合并
|
|
253
|
+
* 的读法因此不变。
|
|
248
254
|
*/
|
|
249
255
|
export declare function createDeploymentGovernanceInputs(config: DeploymentGovernanceConfigView, pathAdjudication: PathAdjudication, roots: DeploymentGovernanceRoots): DeploymentGovernanceInputs;
|
|
250
256
|
/**
|
|
@@ -84,7 +84,7 @@ export function buildOnlySensitiveBaselineWarning(config, seat) {
|
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
86
|
export function createDeploymentGovernanceInputs(config, pathAdjudication, roots) {
|
|
87
|
-
const
|
|
87
|
+
const sensitivePathLayers = config.sensitiveWritePatterns.length > 0
|
|
88
88
|
? (() => {
|
|
89
89
|
const dataRootOpt = roots.engineDataRoot !== undefined ? { dataRoot: roots.engineDataRoot } : {};
|
|
90
90
|
const realTarget = createSensitivePathPolicy({
|
|
@@ -93,20 +93,21 @@ export function createDeploymentGovernanceInputs(config, pathAdjudication, roots
|
|
|
93
93
|
...(pathAdjudication.cwd !== undefined ? { rootPath: pathAdjudication.cwd } : {}),
|
|
94
94
|
...dataRootOpt,
|
|
95
95
|
});
|
|
96
|
-
const transcriptGuard = config.localDataRoot !== undefined
|
|
97
|
-
? createTranscriptIntegrityPolicy({ sessionsDirs: [join(config.localDataRoot, "sessions")] })
|
|
98
|
-
: undefined;
|
|
99
|
-
const withTranscripts = (p) => (transcriptGuard ? combinePolicies(p, transcriptGuard) : p);
|
|
96
|
+
const transcriptGuard = config.localDataRoot !== undefined ? [createTranscriptIntegrityPolicy({ sessionsDirs: [join(config.localDataRoot, "sessions")] })] : [];
|
|
100
97
|
if (pathAdjudication.cwd !== undefined)
|
|
101
|
-
return
|
|
102
|
-
return
|
|
98
|
+
return [realTarget, ...transcriptGuard];
|
|
99
|
+
return [
|
|
100
|
+
scopedToWriteTargetForm(realTarget, "absolute-or-stamped"),
|
|
101
|
+
scopedToWriteTargetForm(createSensitivePathPolicy({ env: new RelativeTargetLexicalEnv(), patterns: config.sensitiveWritePatterns, ...dataRootOpt }), "unstamped-relative"),
|
|
102
|
+
...transcriptGuard,
|
|
103
|
+
];
|
|
103
104
|
})()
|
|
104
105
|
: undefined;
|
|
105
106
|
return {
|
|
106
107
|
autonomy: config.autonomy,
|
|
107
108
|
commandPolicy: config.commandPolicy,
|
|
108
109
|
...(config.manualModeShellGate ? { manualModeShellGate: config.manualModeShellGate } : {}),
|
|
109
|
-
...(
|
|
110
|
+
...(sensitivePathLayers ? { sensitivePathLayers } : {}),
|
|
110
111
|
};
|
|
111
112
|
}
|
|
112
113
|
export function createApprovalBaselinePolicy(config, seat) {
|
|
@@ -63,7 +63,6 @@ export interface HookRunnerContext {
|
|
|
63
63
|
sessionId: string;
|
|
64
64
|
/** hook 命令的工作目录 + payload `cwd` + `CLAUDE_PROJECT_DIR`(host lane 的 session cwd;无则 server cwd)。 */
|
|
65
65
|
cwd: string;
|
|
66
|
-
permissionMode?: string;
|
|
67
66
|
/** 请求自带的 `settings.env`(单用户闸后)——hook 进程 env 与 http $NAME 插值的用户变量通道。 */
|
|
68
67
|
shellEnv?: Record<string, string>;
|
|
69
68
|
/** 阶段三b:`prompt` 条目的模型调用载体(部署组装:一次非流式 completion,费用不折 task budget)。
|
|
@@ -175,7 +174,8 @@ export declare function createTaskHooks(config: HooksConfig, ctx: HookRunnerCont
|
|
|
175
174
|
* 把部署级 hooks 基线(deps.hooks,如 TOOL_TRACE 观测)折进 task 级 hooks——core 是整槽覆盖
|
|
176
175
|
* (`spec.hooks ?? deps.hooks`),不折叠就静默 shadow 部署观测(runtask gateBaseline 注释点名的坑)。
|
|
177
176
|
* 语义:部署槽先跑(观测看到原始输入/输出),task 槽后跑;结果合并:
|
|
178
|
-
* - preToolUse:deny > ask > allow 折叠;updatedInput 串行线程(部署重写喂给 task 槽);context
|
|
177
|
+
* - preToolUse:deny > ask > allow 折叠;updatedInput 串行线程(部署重写喂给 task 槽);context 拼接。读不出词的结果
|
|
178
|
+
* (非对象、集外 `action`)原样交回、由引擎的接手屏判(S-959,短路同 deny)。
|
|
179
179
|
* - postToolUse/postToolUseFailure/postToolBatch:双跑,additionalContext 拼接,updatedOutput 取
|
|
180
180
|
* 后者(task 槽)优先。
|
|
181
181
|
* - userPromptSubmit/stop:部署 block 优先短路(不再跑 task 槽),否则双跑、context 拼接、task block 生效。
|