@sema-agent/server 7.109.0 → 7.111.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 +25 -0
- package/README.md +8 -0
- package/README.zh-CN.md +5 -0
- package/USAGE.md +2 -2
- package/dist/approval-ask-audit-store.d.ts +38 -25
- package/dist/approval-ask-audit-store.js +26 -59
- package/dist/approval-card.d.ts +6 -5
- package/dist/approval-card.js +8 -11
- package/dist/bench/s1/run-firm.d.ts +11 -0
- package/dist/bench/s1/run-firm.js +47 -32
- package/dist/boot/coordinators.js +1 -1
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +3 -2
- package/dist/boot/resolve-spec.js +3 -4
- package/dist/boot/session-faces.d.ts +4 -0
- package/dist/boot/session-faces.js +3 -1
- package/dist/boot/stage-07-capability-layer.d.ts +2 -0
- package/dist/boot/stage-07-capability-layer.js +18 -3
- package/dist/boot/stage-08-reapers.d.ts +2 -0
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +2 -0
- package/dist/boot/stage-09-leader.js +2 -1
- package/dist/boot/stage-10-http-server.d.ts +2 -0
- package/dist/boot/stage-10-http-server.js +2 -1
- package/dist/boot/workflow-orchestration.js +1 -1
- package/dist/config-catalog.js +1 -1
- package/dist/config-types.d.ts +3 -2
- package/dist/config.js +19 -7
- 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/durable-run-leg.js +1 -1
- package/dist/http/resume-legs.js +12 -4
- package/dist/http/routes/runs.d.ts +0 -1
- package/dist/http/routes/runs.js +36 -1
- package/dist/http/routes/sessions.js +12 -2
- package/dist/http/routes/tasks.js +13 -7
- package/dist/http/server.d.ts +5 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/instruction-selection.d.ts +34 -0
- package/dist/instruction-selection.js +23 -0
- package/dist/instruction-source-notice.d.ts +3 -3
- 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 +24 -0
- package/dist/observability/corrupt-read-seat.js +24 -0
- package/dist/observability/fail-open.d.ts +25 -1
- package/dist/observability/fail-open.js +25 -1
- 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/orchestration/workflow-agent-session-index.d.ts +12 -23
- package/dist/orchestration/workflow-agent-session-index.js +11 -50
- package/dist/orchestration/workflow-notify-journal.d.ts +11 -8
- package/dist/orchestration/workflow-notify-journal.js +20 -36
- package/dist/plugins/file-outcome-sink.d.ts +4 -1
- package/dist/plugins/file-outcome-sink.js +9 -3
- package/dist/plugins/file-run-store.js +4 -4
- 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/retention-store-sql.d.ts +1 -1
- package/dist/plugins/retention-store-sql.js +2 -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 +9 -0
- package/dist/plugins/store-contracts.d.ts +24 -0
- package/dist/plugins/store-contracts.js +10 -0
- package/dist/plugins/tidb-pool.js +17 -0
- package/dist/plugins/user-input-ledger-file.d.ts +35 -0
- package/dist/plugins/user-input-ledger-file.js +108 -0
- package/dist/plugins/user-input-ledger-sql.d.ts +54 -0
- package/dist/plugins/user-input-ledger-sql.js +129 -0
- package/dist/project-memory.d.ts +10 -2
- package/dist/project-memory.js +5 -2
- package/dist/run-local.d.ts +18 -5
- package/dist/run-local.js +24 -9
- package/dist/runs.d.ts +8 -1
- package/dist/runs.js +11 -5
- package/dist/runtime-governance.d.ts +20 -8
- 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 +8 -1
- package/dist/tool-approval.js +4 -1
- package/dist/trace/core-keyset-guard.d.ts +16 -1
- package/dist/trace/engine-notice-wire.d.ts +30 -35
- package/dist/trace/engine-notice-wire.js +23 -23
- package/dist/trace/ledger-sink.d.ts +4 -0
- package/dist/trace/ledger-sink.js +1 -1
- package/dist/trace/project.d.ts +11 -3
- package/dist/trace/project.js +6 -5
- package/dist/trace/self-minted-wire.d.ts +40 -0
- package/dist/trace/self-minted-wire.js +15 -0
- package/dist/trace/wire-projection-faces.d.ts +3 -3
- package/dist/trace/wire-projection-faces.js +4 -2
- package/dist/user-input-ledger.d.ts +349 -0
- package/dist/user-input-ledger.js +354 -0
- package/package.json +3 -3
|
@@ -34,7 +34,7 @@ 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";
|
|
@@ -109,7 +109,7 @@ export function createResolveSpec(ctx) {
|
|
|
109
109
|
if (why !== undefined)
|
|
110
110
|
throw new HttpError(422, why, { code: HOST_POSTURE_REFUSED_CODE });
|
|
111
111
|
}
|
|
112
|
-
const lane = bindSettingsCwdEnvAndModel(body, auth, gated,
|
|
112
|
+
const lane = bindSettingsCwdEnvAndModel(body, auth, gated, opts);
|
|
113
113
|
if (auth?.sessionId && assemblyIncarnationRead)
|
|
114
114
|
noteSessionIncarnation(auth.sessionId, await assemblyIncarnationRead(auth.sessionId));
|
|
115
115
|
const anchors = await resolveHistoryAnchors(body, auth);
|
|
@@ -178,7 +178,7 @@ export function createResolveSpec(ctx) {
|
|
|
178
178
|
}
|
|
179
179
|
return { scenarioName, cap, hands: cap.hands, centerDecls, appendLessPack, acceptedAppend, objective, parsedSettings, attachmentNotice };
|
|
180
180
|
};
|
|
181
|
-
const bindSettingsCwdEnvAndModel = (body, auth, gated,
|
|
181
|
+
const bindSettingsCwdEnvAndModel = (body, auth, gated, opts) => {
|
|
182
182
|
const { objective, parsedSettings } = gated;
|
|
183
183
|
const cwdWriteGate = cwdHonored(config) || deviceCwdHonored(config);
|
|
184
184
|
const execLane = executionLaneOf(config.remoteExec?.provider);
|
|
@@ -218,7 +218,6 @@ export function createResolveSpec(ctx) {
|
|
|
218
218
|
logger,
|
|
219
219
|
sessionId: auth?.sessionId ?? "",
|
|
220
220
|
cwd: (auth?.sessionId ? perSessionCwd.get(auth.sessionId) : undefined) ?? process.cwd(),
|
|
221
|
-
permissionMode: effMode ?? ENGINE_ABSENT_PERMISSION_MODE,
|
|
222
221
|
...(parsedSettings.settings?.shellEnv ? { shellEnv: parsedSettings.settings.shellEnv } : {}),
|
|
223
222
|
hookLlm,
|
|
224
223
|
hookAgent,
|
|
@@ -12,6 +12,7 @@ import { SessionWatchRegistry } from "../session-watch.js";
|
|
|
12
12
|
import type { TaskListLane } from "./task-list-lane.js";
|
|
13
13
|
import { type RunnerDeps } from "@sema-agent/core";
|
|
14
14
|
import type { MailboxRecipientLifecycle } from "../plugins/mailbox-recipient-lifecycle.js";
|
|
15
|
+
import type { UserInputLedgerStore } from "../user-input-ledger.js";
|
|
15
16
|
export interface SessionFacesCtx {
|
|
16
17
|
config: ServiceConfig;
|
|
17
18
|
logger: Logger;
|
|
@@ -43,6 +44,9 @@ export interface SessionFacesCtx {
|
|
|
43
44
|
/** S-790 件B:后台子代的耐久店(与 `RunnerDeps.backgroundAgentStore` 同实例)—— 删除协调器据它枚举以本会话为根的子代并结束
|
|
44
45
|
* 它们(E21 级联的一条腿,做完才删元数据)。缺席 = 本部署没有耐久后台子代(纯内存 dev);那一形只剩本进程登记表里的活行,照样停。 */
|
|
45
46
|
backgroundAgentStore: RunnerDeps["backgroundAgentStore"];
|
|
47
|
+
/** S-965:用户输入受理账本的**店**(E21 级联的一条腿:该会话的受理行随会话删)。与受理 / 收敛 / 告知读的是同一只(stage-07 取一次)。
|
|
48
|
+
* 缺席 = 本部署没装账本(env-only:没有 backend / run 店)⇒ 无行可删。 */
|
|
49
|
+
userInputLedgerStore: UserInputLedgerStore | undefined;
|
|
46
50
|
}
|
|
47
51
|
export declare function createSessionFaces(ctx: SessionFacesCtx): {
|
|
48
52
|
ownerAware: OwnerAwareSessionStore;
|
|
@@ -8,7 +8,7 @@ import { defaultTaskRegistry, peerSessionBoxHandle } from "@sema-agent/core";
|
|
|
8
8
|
import { reapSessionBackgroundHard } from "../background-session-reap.js";
|
|
9
9
|
import { probeSessionChildren, retireSessionChildren, SessionChildrenStopIncompleteError } from "../session-children-retire.js";
|
|
10
10
|
export function createSessionFaces(ctx) {
|
|
11
|
-
const { config, logger, metrics, localRoot, backend, sessionStore, runStore, checkpointStore, toolResultStore, resumeAnchorStore, approvalExemptionStore, sessionPolicyStore, taskAttachmentStore, fileHistoryErasure, workflowCompletionInbox, taskListLane, deviceStore, dropSessionScoped, mailboxStore, mailboxRecipientLifecycle, backgroundAgentStore, } = ctx;
|
|
11
|
+
const { config, logger, metrics, localRoot, backend, sessionStore, runStore, checkpointStore, toolResultStore, resumeAnchorStore, approvalExemptionStore, sessionPolicyStore, taskAttachmentStore, fileHistoryErasure, workflowCompletionInbox, taskListLane, deviceStore, dropSessionScoped, mailboxStore, mailboxRecipientLifecycle, backgroundAgentStore, userInputLedgerStore, } = ctx;
|
|
12
12
|
const mysqlPool = backend?.mysqlPool();
|
|
13
13
|
const auditPgPool = backend?.pgPool();
|
|
14
14
|
const auditLocalRoot = backend?.kind === "local" ? (config.localDataRoot ?? localRoot) : undefined;
|
|
@@ -78,6 +78,8 @@ export function createSessionFaces(ctx) {
|
|
|
78
78
|
await sessionPolicyStore.deleteBySession(sessionId);
|
|
79
79
|
if (taskAttachmentStore)
|
|
80
80
|
await taskAttachmentStore.deleteBySession(sessionId);
|
|
81
|
+
if (userInputLedgerStore)
|
|
82
|
+
await userInputLedgerStore.deleteBySession(sessionId);
|
|
81
83
|
if (taskListLane)
|
|
82
84
|
await taskListLane.deleteBySession(sessionId);
|
|
83
85
|
if (deviceStore)
|
|
@@ -23,6 +23,8 @@ 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;
|
|
27
|
+
userInputLedgerStore: import("../user-input-ledger.js").UserInputLedgerStore | undefined;
|
|
26
28
|
webSearchProvider: "brave" | "tavily" | "searxng" | undefined;
|
|
27
29
|
approvalAskAudit: import("../approval-ask-audit-store.js").FileApprovalAskAuditStore | undefined;
|
|
28
30
|
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,20 @@ 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 userInputLedgerStore = backend && runStore ? backend.userInputLedger() : undefined;
|
|
55
|
+
const userInputLedger = backend && runStore && userInputLedgerStore
|
|
56
|
+
? await (async () => {
|
|
57
|
+
const { ledger, converged } = await createUserInputLedgerAtBoot({
|
|
58
|
+
store: userInputLedgerStore,
|
|
59
|
+
writer: instanceId,
|
|
60
|
+
evidence: writerGoneEvidenceFor(backend.kind, runStore),
|
|
61
|
+
newId: uuidv7,
|
|
62
|
+
});
|
|
63
|
+
if (converged > 0)
|
|
64
|
+
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" });
|
|
65
|
+
return ledger;
|
|
66
|
+
})()
|
|
67
|
+
: undefined;
|
|
53
68
|
const imageIndex = backend?.imageIndex ? backend.imageIndex() : undefined;
|
|
54
69
|
const selectEnvTool = config.selectEnvironmentTool && config.remoteExec?.provider === "k8s" && imageIndex
|
|
55
70
|
? selectEnvironmentTool({
|
|
@@ -156,6 +171,6 @@ export async function runStage07(ctx) {
|
|
|
156
171
|
const builtinScenarioNames = Object.keys(scenarioDetails);
|
|
157
172
|
configCenter.applyCenterScenarios({ scenarioDeps, scenarios, scenarioDetails, builtinScenarioNames });
|
|
158
173
|
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 };
|
|
174
|
+
return { ...ctx, approvalExemptionStore, approvalNonceStore, authorize, imageBakes, imageIndex, parkedReviveInheritedGate, parkedReviveSurface, rateLimiter, resumeAnchorStore, runStore, scenarioDetails, scenarios, selectEnvTool, taskLimitCaps, taskTimeoutSec, userInputLedger, userInputLedgerStore, webSearchProvider: webSearchCfg?.provider };
|
|
160
175
|
}
|
|
161
176
|
//# sourceMappingURL=stage-07-capability-layer.js.map
|
|
@@ -36,6 +36,8 @@ 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;
|
|
40
|
+
userInputLedgerStore: import("../user-input-ledger.js").UserInputLedgerStore | undefined;
|
|
39
41
|
webSearchProvider: "brave" | "tavily" | "searxng" | undefined;
|
|
40
42
|
approvalAskAudit: import("../approval-ask-audit-store.js").FileApprovalAskAuditStore | undefined;
|
|
41
43
|
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,8 @@ 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;
|
|
76
|
+
userInputLedgerStore: import("../user-input-ledger.js").UserInputLedgerStore | undefined;
|
|
75
77
|
webSearchProvider: "brave" | "tavily" | "searxng" | undefined;
|
|
76
78
|
approvalAskAudit: import("../approval-ask-audit-store.js").FileApprovalAskAuditStore | undefined;
|
|
77
79
|
centerRuntimeCapsResolver: ((principal: string | undefined) => Promise<import("@sema-agent/core").RuntimeCaps | undefined>) | undefined;
|
|
@@ -6,7 +6,7 @@ import { createLeaderFace } from "./leader.js";
|
|
|
6
6
|
import { assertStaticWiringConsistent } from "../http/routes/diagnostics.js";
|
|
7
7
|
import { buildDisplaySafeUrl } from "../trace/redact.js";
|
|
8
8
|
export function runStage09(ctx) {
|
|
9
|
-
const { approvalExemptionStore, backend, backgroundAgentStore, brain, checkpointStore, config, configCenter, deviceLane, dropSessionScoped, durableEnabled, executionEnvFactory, fileHistoryErasure, governanceSeams, localRoot, logger, mailboxRecipientLifecycle, mailboxStore, metrics, pricing, resumeAnchorStore, runStore, runnerDeps, sessionPolicyStore, sessionStore, streamApprovalGate, taskAttachmentStore, taskListLane, toolResultStore, tracer, usageWindowStore, workflowCompletionInbox } = ctx;
|
|
9
|
+
const { approvalExemptionStore, backend, backgroundAgentStore, brain, checkpointStore, config, configCenter, deviceLane, dropSessionScoped, durableEnabled, executionEnvFactory, fileHistoryErasure, governanceSeams, localRoot, logger, mailboxRecipientLifecycle, mailboxStore, metrics, pricing, resumeAnchorStore, runStore, runnerDeps, sessionPolicyStore, sessionStore, streamApprovalGate, taskAttachmentStore, taskListLane, toolResultStore, tracer, usageWindowStore, userInputLedgerStore, workflowCompletionInbox } = ctx;
|
|
10
10
|
const { ownerAware, sessionAudit, sessionWatchRegistry, purgeSession, instrumentDegenerate, planCacheProbe } = createSessionFaces({
|
|
11
11
|
deviceStore: deviceLane?.store,
|
|
12
12
|
dropSessionScoped,
|
|
@@ -14,6 +14,7 @@ export function runStage09(ctx) {
|
|
|
14
14
|
resumeAnchorStore, approvalExemptionStore, sessionPolicyStore, taskAttachmentStore, fileHistoryErasure,
|
|
15
15
|
workflowCompletionInbox, taskListLane, mailboxStore, mailboxRecipientLifecycle,
|
|
16
16
|
backgroundAgentStore,
|
|
17
|
+
userInputLedgerStore,
|
|
17
18
|
});
|
|
18
19
|
const leaderEndpoint = createLeaderFace({ config, logger, brain, pricing, executionEnvFactory, toolResultStore, sessionStore, checkpointStore, governanceSeams, backend, tracer, usageWindowStore, promptSource: configCenter.promptSource, onError: runnerDeps.onError });
|
|
19
20
|
const drainState = { draining: false };
|
|
@@ -72,6 +72,8 @@ 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;
|
|
76
|
+
userInputLedgerStore: import("../user-input-ledger.js").UserInputLedgerStore | undefined;
|
|
75
77
|
webSearchProvider: "brave" | "tavily" | "searxng" | undefined;
|
|
76
78
|
approvalAskAudit: import("../approval-ask-audit-store.js").FileApprovalAskAuditStore | undefined;
|
|
77
79
|
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;
|
|
@@ -20,7 +20,7 @@ export function createWorkflowOrchestration(ctx) {
|
|
|
20
20
|
}))
|
|
21
21
|
: undefined;
|
|
22
22
|
const workflowNotifyJournal = config.selfOrchestrationEnabled && config.workflowRunStoreBackend !== "memory"
|
|
23
|
-
? (sqlWorkflowRunStore ? backend.notifyJournal() : new FileWorkflowNotifyJournalStore(join(config.localDataRoot ?? localRoot, "workflows")))
|
|
23
|
+
? (sqlWorkflowRunStore ? backend.notifyJournal() : new FileWorkflowNotifyJournalStore(join(config.localDataRoot ?? localRoot, "workflows"), undefined, (msg, meta) => logger.warn(msg, meta)))
|
|
24
24
|
: undefined;
|
|
25
25
|
const workflowCompletionInbox = config.selfOrchestrationEnabled
|
|
26
26
|
? config.workflowRunStoreBackend === "memory"
|
package/dist/config-catalog.js
CHANGED
|
@@ -244,7 +244,7 @@ export const CONFIG_CATALOG = [
|
|
|
244
244
|
r("MEMORY_SCOPE", "memory", "string", "单用户部署的记忆 scope 名", { derivedDefaultNote: "缺席:引擎开 ∧ 单用户 ⇒ local;其余 ⇒ 缺席(记忆暗)", configKey: "memoryScope" }),
|
|
245
245
|
r("MEMORY_SYNC_MAX_PULL_ENTRIES", "memory", "number", "TOC 同步单轮 pull 条数帽(设了必须 ≥1 整数)", { derivedDefaultNote: "缺席 ⇒ 键缺席,core 默认" }),
|
|
246
246
|
r("MEMORY_SYNC_MAX_PUSH_ENTRIES", "memory", "number", "TOC 同步单轮 push 条数帽(设了必须 ≥1 整数)", { derivedDefaultNote: "缺席 ⇒ 键缺席,core 默认" }),
|
|
247
|
-
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)" }),
|
|
248
248
|
r("MEMORY_SYNC_TOKEN", "memory", "secret", "TOC 同步中心面的 Bearer(URL 设了它必须在,半配拒启)", { danger: SEC }),
|
|
249
249
|
r("MEMORY_SYNC_URL", "memory", "url", "TOC 同步中心地址(设了=开;file 记忆形专用,DB 后端配了拒启;同步只覆盖一层 ⇒ 单用户任务不按项目键控、写家落全局层 MEMORY_SCOPE(S-512 让位,启动通知 `memory_project_scope_yields_to_sync`))"),
|
|
250
250
|
r("METRICS_TOKEN", "observability", "secret", "/metrics 只读令牌", { danger: SEC }),
|
package/dist/config-types.d.ts
CHANGED
|
@@ -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?: {
|
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";
|
|
@@ -1666,9 +1666,14 @@ function parseMemoryDomain(ctx) {
|
|
|
1666
1666
|
if (memorySyncToken === undefined) {
|
|
1667
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)");
|
|
1668
1668
|
}
|
|
1669
|
-
|
|
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;
|
|
1670
1675
|
if (scope === undefined) {
|
|
1671
|
-
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");
|
|
1672
1677
|
}
|
|
1673
1678
|
memorySync = {
|
|
1674
1679
|
url: memorySyncUrl,
|
|
@@ -1680,15 +1685,22 @@ function parseMemoryDomain(ctx) {
|
|
|
1680
1685
|
}
|
|
1681
1686
|
const replication = memoryReplicationCoverage(memorySync !== undefined ? { memorySync } : {});
|
|
1682
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
|
+
};
|
|
1683
1697
|
CONFIG_NOTICES.push({
|
|
1684
1698
|
level: "warn",
|
|
1685
1699
|
event: "memory_project_scope_yields_to_sync",
|
|
1686
1700
|
fields: {
|
|
1687
1701
|
replicatedScopes: replication.scopes.join(","),
|
|
1688
1702
|
writeScope: memoryScope,
|
|
1689
|
-
hint:
|
|
1690
|
-
"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 " +
|
|
1691
|
-
"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"],
|
|
1692
1704
|
},
|
|
1693
1705
|
});
|
|
1694
1706
|
}
|
|
@@ -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 生效。
|
|
@@ -648,12 +648,12 @@ async function runMatchingEntries(event, groups, matchValue, payload, ctx, onceF
|
|
|
648
648
|
}
|
|
649
649
|
return results;
|
|
650
650
|
}
|
|
651
|
-
function basePayload(ctx) {
|
|
651
|
+
function basePayload(ctx, permissionMode) {
|
|
652
652
|
return {
|
|
653
653
|
session_id: ctx.sessionId,
|
|
654
654
|
transcript_path: "",
|
|
655
655
|
cwd: ctx.cwd,
|
|
656
|
-
...(
|
|
656
|
+
...(permissionMode !== undefined ? { permission_mode: permissionMode } : {}),
|
|
657
657
|
};
|
|
658
658
|
}
|
|
659
659
|
function ignoreMatchers(groups) {
|
|
@@ -732,7 +732,7 @@ export function createTaskHooks(config, ctx) {
|
|
|
732
732
|
if (!m)
|
|
733
733
|
continue;
|
|
734
734
|
const payload = {
|
|
735
|
-
...basePayload(ctx),
|
|
735
|
+
...basePayload(ctx, tctx.permissionMode),
|
|
736
736
|
hook_event_name: "PreToolUse",
|
|
737
737
|
tool_name: toolName,
|
|
738
738
|
tool_input: currentInput,
|
|
@@ -827,7 +827,7 @@ export function createTaskHooks(config, ctx) {
|
|
|
827
827
|
.map((c) => (c && typeof c === "object" && typeof c.text === "string" ? c.text : ""))
|
|
828
828
|
.join("");
|
|
829
829
|
const payload = {
|
|
830
|
-
...basePayload(ctx),
|
|
830
|
+
...basePayload(ctx, tctx.permissionMode),
|
|
831
831
|
hook_event_name: "PostToolUse",
|
|
832
832
|
tool_name: toolName,
|
|
833
833
|
tool_input: input,
|
|
@@ -876,7 +876,7 @@ export function createTaskHooks(config, ctx) {
|
|
|
876
876
|
const postToolUseFailureHook = async (toolName, input, f, tctx) => {
|
|
877
877
|
const contexts = [];
|
|
878
878
|
const payload = {
|
|
879
|
-
...basePayload(ctx),
|
|
879
|
+
...basePayload(ctx, tctx.permissionMode),
|
|
880
880
|
hook_event_name: "PostToolUseFailure",
|
|
881
881
|
tool_name: toolName,
|
|
882
882
|
tool_input: input,
|
|
@@ -919,10 +919,10 @@ export function createTaskHooks(config, ctx) {
|
|
|
919
919
|
hooks.postToolUseFailure = postToolUseFailureHook;
|
|
920
920
|
}
|
|
921
921
|
if (postBatch) {
|
|
922
|
-
const postToolBatchHook = async (calls) => {
|
|
922
|
+
const postToolBatchHook = async (calls, _meta, bctx) => {
|
|
923
923
|
const contexts = [];
|
|
924
924
|
const payload = {
|
|
925
|
-
...basePayload(ctx),
|
|
925
|
+
...basePayload(ctx, bctx?.permissionMode),
|
|
926
926
|
hook_event_name: "PostToolBatch",
|
|
927
927
|
tool_calls: calls.map((c) => ({
|
|
928
928
|
tool_name: c.toolName,
|
|
@@ -962,9 +962,9 @@ export function createTaskHooks(config, ctx) {
|
|
|
962
962
|
hooks.postToolBatch = postToolBatchHook;
|
|
963
963
|
}
|
|
964
964
|
if (promptSubmit) {
|
|
965
|
-
const userPromptSubmitHook = async (prompt) => {
|
|
965
|
+
const userPromptSubmitHook = async (prompt, uctx) => {
|
|
966
966
|
const contexts = [];
|
|
967
|
-
const payload = { ...basePayload(ctx), hook_event_name: "UserPromptSubmit", prompt: clip(prompt, MAX_TOOL_INPUT_CHARS) };
|
|
967
|
+
const payload = { ...basePayload(ctx, uctx?.permissionMode), hook_event_name: "UserPromptSubmit", prompt: clip(prompt, MAX_TOOL_INPUT_CHARS) };
|
|
968
968
|
const singles = await runMatchingEntries("UserPromptSubmit", ignoreMatchers(promptSubmit), "", payload, ctx, onceFired, Date.now() + MAX_HOOK_EVENT_TOTAL_SECONDS * 1000);
|
|
969
969
|
for (const { entry, run } of singles) {
|
|
970
970
|
if (run.code === 2) {
|
|
@@ -1003,7 +1003,7 @@ export function createTaskHooks(config, ctx) {
|
|
|
1003
1003
|
}
|
|
1004
1004
|
if (stopEntries) {
|
|
1005
1005
|
const stopHook = async (sctx) => {
|
|
1006
|
-
const payload = { ...basePayload(ctx), hook_event_name: "Stop", stop_hook_active: sctx.stopHookActive };
|
|
1006
|
+
const payload = { ...basePayload(ctx, sctx.permissionMode), hook_event_name: "Stop", stop_hook_active: sctx.stopHookActive };
|
|
1007
1007
|
let llmExtra;
|
|
1008
1008
|
const wantsPrompt = stopEntries.some((g) => g.hooks.some((h) => h.type === "prompt"));
|
|
1009
1009
|
if (wantsPrompt) {
|
|
@@ -1097,7 +1097,7 @@ export function createTaskHooks(config, ctx) {
|
|
|
1097
1097
|
const stopFailureHook = async (fctx) => {
|
|
1098
1098
|
const turnError = toAssistantTurnError(fctx.errorKind);
|
|
1099
1099
|
const payload = {
|
|
1100
|
-
...basePayload(ctx),
|
|
1100
|
+
...basePayload(ctx, undefined),
|
|
1101
1101
|
hook_event_name: "StopFailure",
|
|
1102
1102
|
error: turnError,
|
|
1103
1103
|
...(fctx.error ? { error_details: clip(redactSecrets(fctx.error), MAX_HOOK_FEEDBACK_CHARS) } : {}),
|
|
@@ -1109,7 +1109,7 @@ export function createTaskHooks(config, ctx) {
|
|
|
1109
1109
|
if (preCompactEntries) {
|
|
1110
1110
|
const preCompactHook = async (pctx) => {
|
|
1111
1111
|
const payload = {
|
|
1112
|
-
...basePayload(ctx),
|
|
1112
|
+
...basePayload(ctx, undefined),
|
|
1113
1113
|
hook_event_name: "PreCompact",
|
|
1114
1114
|
trigger: pctx.trigger,
|
|
1115
1115
|
custom_instructions: pctx.customInstructions ?? null,
|
|
@@ -1143,7 +1143,7 @@ export function createTaskHooks(config, ctx) {
|
|
|
1143
1143
|
if (postCompactEntries) {
|
|
1144
1144
|
const postCompactHook = async (cctx) => {
|
|
1145
1145
|
const payload = {
|
|
1146
|
-
...basePayload(ctx),
|
|
1146
|
+
...basePayload(ctx, undefined),
|
|
1147
1147
|
hook_event_name: "PostCompact",
|
|
1148
1148
|
trigger: cctx.trigger,
|
|
1149
1149
|
compact_summary: clip(cctx.summary, MAX_TOOL_RESPONSE_CHARS),
|
|
@@ -1191,16 +1191,30 @@ export function composeHooks(deployment, task) {
|
|
|
1191
1191
|
if (!slot)
|
|
1192
1192
|
continue;
|
|
1193
1193
|
const r = await slot(toolName, current, ctx);
|
|
1194
|
-
if (
|
|
1194
|
+
if (r === undefined || Object.is(r, null) || Object.is(r, false))
|
|
1195
1195
|
continue;
|
|
1196
|
+
if (typeof r !== "object")
|
|
1197
|
+
return r;
|
|
1196
1198
|
if (r.additionalContext)
|
|
1197
1199
|
contexts.push(r.additionalContext);
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1200
|
+
const action = r.action;
|
|
1201
|
+
const updatedInput = r.updatedInput;
|
|
1202
|
+
switch (action) {
|
|
1203
|
+
case "deny":
|
|
1204
|
+
return { ...r, ...buildHookContextField(contexts) };
|
|
1205
|
+
case "ask":
|
|
1206
|
+
asked = r;
|
|
1207
|
+
break;
|
|
1208
|
+
case "allow":
|
|
1209
|
+
case undefined:
|
|
1210
|
+
if (updatedInput !== undefined)
|
|
1211
|
+
current = updatedInput;
|
|
1212
|
+
break;
|
|
1213
|
+
default: {
|
|
1214
|
+
const unread = action;
|
|
1215
|
+
void unread;
|
|
1216
|
+
return r;
|
|
1217
|
+
}
|
|
1204
1218
|
}
|
|
1205
1219
|
}
|
|
1206
1220
|
if (asked) {
|
|
@@ -1245,20 +1259,20 @@ export function composeHooks(deployment, task) {
|
|
|
1245
1259
|
};
|
|
1246
1260
|
}
|
|
1247
1261
|
if (d.postToolBatch || t.postToolBatch) {
|
|
1248
|
-
out.postToolBatch = async (calls) => {
|
|
1249
|
-
const rd = d.postToolBatch ? await d.postToolBatch(calls) : undefined;
|
|
1250
|
-
const rt = t.postToolBatch ? await t.postToolBatch(calls) : undefined;
|
|
1262
|
+
out.postToolBatch = async (calls, meta, bctx) => {
|
|
1263
|
+
const rd = d.postToolBatch ? await d.postToolBatch(calls, meta, bctx) : undefined;
|
|
1264
|
+
const rt = t.postToolBatch ? await t.postToolBatch(calls, meta, bctx) : undefined;
|
|
1251
1265
|
const contexts = [rd?.additionalContext, rt?.additionalContext].filter((c) => typeof c === "string" && c.length > 0);
|
|
1252
1266
|
const additionalContext = buildHookContext(contexts);
|
|
1253
1267
|
return additionalContext === undefined ? undefined : { additionalContext };
|
|
1254
1268
|
};
|
|
1255
1269
|
}
|
|
1256
1270
|
if (d.userPromptSubmit || t.userPromptSubmit) {
|
|
1257
|
-
out.userPromptSubmit = async (prompt) => {
|
|
1258
|
-
const rd = d.userPromptSubmit ? await d.userPromptSubmit(prompt) : undefined;
|
|
1271
|
+
out.userPromptSubmit = async (prompt, uctx) => {
|
|
1272
|
+
const rd = d.userPromptSubmit ? await d.userPromptSubmit(prompt, uctx) : undefined;
|
|
1259
1273
|
if (rd?.block)
|
|
1260
1274
|
return { ...rd, ...buildHookContextField(rd.additionalContext ? [rd.additionalContext] : []) };
|
|
1261
|
-
const rt = t.userPromptSubmit ? await t.userPromptSubmit(prompt) : undefined;
|
|
1275
|
+
const rt = t.userPromptSubmit ? await t.userPromptSubmit(prompt, uctx) : undefined;
|
|
1262
1276
|
if (!rd && !rt)
|
|
1263
1277
|
return undefined;
|
|
1264
1278
|
const contexts = [rd?.additionalContext, rt?.additionalContext].filter((c) => typeof c === "string" && c.length > 0);
|
|
@@ -63,7 +63,7 @@ export async function mintAndDriveDurableRun(ctx, runStore, args) {
|
|
|
63
63
|
windowMs: deps.config.streamApproval?.windowMs,
|
|
64
64
|
windowMarginMs: deps.config.streamAskWindowMarginMs,
|
|
65
65
|
}
|
|
66
|
-
: undefined, deps.checkpointStore, args.prepared.engineNotices, args.trustedInternals);
|
|
66
|
+
: undefined, deps.checkpointStore, args.prepared.engineNotices, args.trustedInternals, deps.userInputLedger);
|
|
67
67
|
return { status: 202, body: { taskId, sessionId, status: "running" } };
|
|
68
68
|
}
|
|
69
69
|
//# sourceMappingURL=durable-run-leg.js.map
|