@sema-agent/server 7.96.0 → 7.98.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 +5 -0
- package/README.md +2 -2
- package/README.zh-CN.md +2 -2
- package/USAGE.md +10 -1
- package/deploy/sema-up/cluster-up.sh +8 -4
- package/deploy/sema-up/kube-up.sh +40 -15
- package/deploy/sema-up/lib/envf.sh +173 -0
- package/deploy/sema-up/sema-up.sh +113 -94
- package/deploy/sema-up/smoke.sh +8 -1
- package/dist/approval.d.ts +28 -0
- package/dist/approval.js +24 -0
- package/dist/boot/budget-tracing.d.ts +1 -0
- package/dist/boot/budget-tracing.js +3 -2
- package/dist/boot/config-center.js +4 -7
- package/dist/boot/coordinators.js +2 -2
- package/dist/boot/deferred-sandbox-path-env.d.ts +5 -2
- package/dist/boot/deferred-sandbox-path-env.js +3 -1
- package/dist/boot/memory-boundary.d.ts +17 -2
- package/dist/boot/memory-boundary.js +11 -0
- package/dist/boot/reapers.d.ts +3 -1
- package/dist/boot/reapers.js +2 -2
- package/dist/boot/resolve-spec.js +15 -10
- package/dist/boot/runner-deps.d.ts +2 -1
- package/dist/boot/session-faces.d.ts +4 -1
- package/dist/boot/session-faces.js +5 -5
- package/dist/boot/stage-04-stores.d.ts +1 -0
- package/dist/boot/stage-04-stores.js +2 -2
- package/dist/boot/stage-05-execution-env.d.ts +1 -0
- package/dist/boot/stage-06-runners.d.ts +1 -0
- package/dist/boot/stage-07-capability-layer.d.ts +1 -0
- package/dist/boot/stage-07-capability-layer.js +10 -14
- package/dist/boot/stage-08-reapers.d.ts +2 -3
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +1 -0
- package/dist/boot/stage-09-leader.js +2 -2
- package/dist/boot/stage-10-http-server.d.ts +1 -0
- package/dist/boot/stores.js +5 -11
- package/dist/brain.js +28 -18
- package/dist/capabilities/execution-lane.d.ts +5 -7
- package/dist/capabilities/execution-lane.js +2 -1
- package/dist/capabilities/memory-notice.d.ts +30 -12
- package/dist/capabilities/memory-notice.js +8 -1
- package/dist/capabilities/skills.d.ts +14 -0
- package/dist/capabilities/skills.js +4 -0
- package/dist/config-catalog.js +5 -4
- package/dist/config-center/apply-effective.js +7 -1
- package/dist/config-center/facade.d.ts +2 -1
- package/dist/config-invariants.d.ts +2 -2
- package/dist/config-invariants.js +9 -1
- package/dist/config-types.d.ts +20 -3
- package/dist/config.d.ts +9 -0
- package/dist/config.js +46 -8
- package/dist/env-facts.js +2 -4
- package/dist/execution-lane-caps.d.ts +36 -6
- package/dist/execution-lane-caps.js +4 -0
- package/dist/file-history-capture.d.ts +65 -0
- package/dist/file-history-capture.js +21 -0
- package/dist/hooks/hook-llm.d.ts +1 -1
- package/dist/hooks/hook-llm.js +3 -1
- package/dist/hosted-posture.d.ts +1 -1
- package/dist/http/resume-legs.d.ts +14 -4
- package/dist/http/resume-legs.js +26 -17
- package/dist/http/route-ctx.d.ts +35 -9
- package/dist/http/routes/approvals-assistant.d.ts +1 -1
- package/dist/http/routes/approvals-assistant.js +16 -6
- package/dist/http/routes/capabilities.js +2 -0
- package/dist/http/routes/runs.js +2 -2
- package/dist/http/routes/session-sync.js +6 -1
- package/dist/http/server.d.ts +4 -1
- package/dist/http/server.js +1 -1
- package/dist/http/verify-rounds.d.ts +1 -1
- package/dist/memory-scope.d.ts +68 -13
- package/dist/memory-scope.js +35 -5
- package/dist/model-provider.d.ts +13 -0
- package/dist/model-provider.js +3 -0
- package/dist/model-route-endpoint.d.ts +82 -0
- package/dist/model-route-endpoint.js +55 -0
- package/dist/observability/fail-open.d.ts +4 -0
- package/dist/observability/fail-open.js +4 -0
- package/dist/project-identity.d.ts +29 -0
- package/dist/project-identity.js +120 -0
- package/dist/run-local.d.ts +14 -4
- package/dist/run-local.js +12 -10
- package/dist/session-sync.d.ts +4 -1
- package/dist/session-sync.js +2 -2
- package/dist/task-cwd.d.ts +9 -3
- package/dist/task-cwd.js +3 -1
- package/dist/trace/redact.d.ts +1 -1
- package/package.json +1 -1
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
* `TaskSpec.memoryPersistenceCapable` 一条路进去(`boot/resolve-spec.ts` 直通),我方显式**不铸**受限会话、
|
|
55
55
|
* 也**不投**这个读面(硬造一个消费点 = 造给自己看的 wire 键)。哪天真要在诊断面露它,先有消费方需求。
|
|
56
56
|
*/
|
|
57
|
+
import { type ExecutionLane, type RemoteExecProvider } from "../execution-lane-caps.js";
|
|
57
58
|
/**
|
|
58
59
|
* [ref] A3 源头修(黑板 [ref]/[ref]/[ref],[ref])—— `memoryPersistenceCapable` 的**装配层有效值**:
|
|
59
60
|
* operator 显式 env 恒赢;env 缺席时,`REMOTE_EXEC=host` 腿自动补 `true`;其余一律缺席(现行为)。
|
|
@@ -93,8 +94,8 @@ export interface MemoryWriteBoundaryFacts {
|
|
|
93
94
|
* core 7.16.0([ref])之后写家还要再深一层(`<平面>/<label>`),但 label 归引擎注册簿,boot 期说不出口;
|
|
94
95
|
* 平面是**包含关系上等价**的那一只(家恒为平面的直接子目录),所以判据停在平面,不猜 label。 */
|
|
95
96
|
memoryRoot: string | undefined;
|
|
96
|
-
/** 执行车道名,只进文案(`
|
|
97
|
-
lane:
|
|
97
|
+
/** 执行车道名,只进文案(归一读口 `executionLaneOf` 的答案;S-602 起不在调用点手写 `?? "in-process"`)。 */
|
|
98
|
+
lane: ExecutionLane;
|
|
98
99
|
/** 该车道的文件工具是否跑在**本机** fs 上(in-process / `REMOTE_EXEC=host`)。false = 沙箱盘,与记忆根分平面。
|
|
99
100
|
* ⚠️ 这一位管的是**文件平面**,与下面的 `coreRemoteExecutionEnv` 是**两根轴**,别合并(codex round2
|
|
100
101
|
* [medium] 就是把它们当成一根轴的后果):`host` 车道的文件平面就是本机(这一位 true),但 core 眼里它
|
|
@@ -116,6 +117,20 @@ export interface MemoryWriteBoundaryFacts {
|
|
|
116
117
|
/** boot 期算得出的文件工具围栏根。空数组 = 算不出(每任务临时目录 / 未配 workspace)⇒ 不判。 */
|
|
117
118
|
containmentRoots: readonly string[];
|
|
118
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* S-602 —— 审计的**车道那四位**由本函数从能力表派生(boot/stores.ts 的装配点只调它,不再就地手写):
|
|
122
|
+
* 改前 stores 里是 `lane === undefined || lane === "host"`(同义折,门 D R3)+ `config.remoteExec !== undefined`
|
|
123
|
+
* (座位上的裸缺席判,R4)+ `lane ?? "in-process"` ×3(R2)。两根轴各读表里各自那一位,不合并:
|
|
124
|
+
* · `hostSemanticsLane` ⇐ `hostFilePlane`(文件平面在不在本机);
|
|
125
|
+
* · `coreRemoteExecutionEnv` ⇐ 同名位(core 拿没拿到执行环境)。
|
|
126
|
+
* 读数逐车道不变(对账:`test/execution-lane-caps.test.ts` 的真装配点联合覆盖格)。`processCwd` 由调用点传
|
|
127
|
+
* (stores 传 `process.cwd()`),本函数保持纯。
|
|
128
|
+
*/
|
|
129
|
+
export declare function buildMemoryBoundaryLaneFacts(config: {
|
|
130
|
+
readonly remoteExec?: {
|
|
131
|
+
readonly provider: RemoteExecProvider;
|
|
132
|
+
} | undefined;
|
|
133
|
+
}, processCwd: string): Pick<MemoryWriteBoundaryFacts, "lane" | "hostSemanticsLane" | "coreRemoteExecutionEnv" | "containmentRoots">;
|
|
119
134
|
/** 一条启动告警:`tag` 进日志事件名(可被运维按名过滤/告警),`detail` 是给人读的整句(含恢复路径)。 */
|
|
120
135
|
export interface MemoryWriteBoundaryWarning {
|
|
121
136
|
tag: "memory_root_outside_write_boundary" | "memory_remote_lane_write_instruction_dropped";
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
|
+
import { executionLaneCaps, executionLaneOf } from "../execution-lane-caps.js";
|
|
2
3
|
export function effectiveMemoryPersistenceCapable(config) {
|
|
3
4
|
if (config.memoryPersistenceCapable !== undefined)
|
|
4
5
|
return config.memoryPersistenceCapable;
|
|
5
6
|
return config.remoteExec?.provider === "host" ? true : undefined;
|
|
6
7
|
}
|
|
8
|
+
export function buildMemoryBoundaryLaneFacts(config, processCwd) {
|
|
9
|
+
const lane = executionLaneOf(config.remoteExec?.provider);
|
|
10
|
+
const caps = executionLaneCaps(lane);
|
|
11
|
+
return {
|
|
12
|
+
lane,
|
|
13
|
+
hostSemanticsLane: caps.hostFilePlane === "supported",
|
|
14
|
+
coreRemoteExecutionEnv: caps.coreRemoteExecutionEnv === "supported",
|
|
15
|
+
containmentRoots: lane === "in-process" ? [processCwd] : [],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
7
18
|
function isInside(child, root) {
|
|
8
19
|
const c = resolve(child);
|
|
9
20
|
const r = resolve(root);
|
package/dist/boot/reapers.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ import type { Logger } from "../observability/logger.js";
|
|
|
20
20
|
import type { Metrics } from "../observability/metrics.js";
|
|
21
21
|
import type { WorkflowNotifyGate, WorkflowNotifyJournalStore } from "../orchestration/workflow-notify-journal.js";
|
|
22
22
|
import type { TaskAttachmentStore } from "../plugins/task-attachment-store.js";
|
|
23
|
+
import type { FileHistoryErasureFace } from "../file-history-capture.js";
|
|
23
24
|
import type { ApprovalNonceStore, CheckpointStoreFull, CostQuotaStore, ImageBake, RateLimiterStore, ServiceWorkflowJournalStore, StoreBackend, ToolResultStoreFull } from "../plugins/store-backend.js";
|
|
24
25
|
import type { ToolApprovalCoordinator } from "../tool-approval.js";
|
|
25
26
|
/** [ref] / [ref]§五(sema-comms `audits/failopen-governance-176.md` §7 "Z 类 1 条"):default consecutive-failure
|
|
@@ -69,7 +70,8 @@ export interface ReapersCtx {
|
|
|
69
70
|
rateLimiter: RateLimiter | RateLimiterStore | undefined;
|
|
70
71
|
costQuota: CostQuota | CostQuotaStore | undefined;
|
|
71
72
|
toolResultStore: ToolResultStoreFull | undefined;
|
|
72
|
-
|
|
73
|
+
/** S-589:文件历史的**擦除脸**(后端在即在,与 `FILE_HISTORY_CAPTURE` 无关)—— 本段只用它的孤儿 blob GC。 */
|
|
74
|
+
fileHistoryErasure: FileHistoryErasureFace | undefined;
|
|
73
75
|
taskAttachmentStore: TaskAttachmentStore | undefined;
|
|
74
76
|
imageBakes: ImageBake | undefined;
|
|
75
77
|
worktreeReap: (() => Promise<void>) | undefined;
|
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,
|
|
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;
|
|
60
60
|
const leg = (p) => {
|
|
61
61
|
if (p !== undefined)
|
|
62
62
|
trackMaintenanceLeg(p);
|
|
@@ -227,7 +227,7 @@ export function startReapers(ctx) {
|
|
|
227
227
|
leg(toolResultStore
|
|
228
228
|
?.reapOlderThan?.(Date.now() - config.toolResultTtlSec * 1000)
|
|
229
229
|
?.then(() => toolResultReapOlderThanGuard.onSuccess(), toolResultReapOlderThanGuard.onError));
|
|
230
|
-
leg(
|
|
230
|
+
leg(fileHistoryErasure
|
|
231
231
|
?.sweepOrphanBlobs?.()
|
|
232
232
|
.then(() => fileHistorySweepOrphanBlobsGuard.onSuccess(), fileHistorySweepOrphanBlobsGuard.onError));
|
|
233
233
|
leg(backend?.legacySnapshotBlobSweep?.()
|
|
@@ -7,7 +7,7 @@ import { SessionEnvironmentSelection, selectEnvironmentTool } from "../capabilit
|
|
|
7
7
|
import { sendUserFileTool } from "../capabilities/send-user-file-tool.js";
|
|
8
8
|
import { gateScenarioRequest, mergeUserSkills, selectScenario } from "../capabilities/scenarios.js";
|
|
9
9
|
import { stampHandsLane, toolPolicyForHands } from "../capabilities/hands-lane.js";
|
|
10
|
-
import { shouldDiscloseNoPersistentMemory, withNoPersistentMemoryNotice } from "../capabilities/memory-notice.js";
|
|
10
|
+
import { buildNoticeLaneFacts, shouldDiscloseNoPersistentMemory, withNoPersistentMemoryNotice } from "../capabilities/memory-notice.js";
|
|
11
11
|
import { applyLongtailDefer } from "../capabilities/tool-defer.js";
|
|
12
12
|
import { assertGuardPatternsUsable, buildOnlySensitiveBaselineWarning, createApprovalBaselinePolicy, createDeploymentGovernanceInputs } from "../deployment-governance.js";
|
|
13
13
|
import { acceptShellScratchpadDir, buildEnvFacts, egressForRemoteExec, ensureScratchpadDir, resumeFactsForLane, scratchpadCoveringTaskRoot } from "../env-facts.js";
|
|
@@ -25,7 +25,7 @@ import { isIsolatedExecEnv, routeServiceTask, supPostureOverrides } from "../rou
|
|
|
25
25
|
import { gateExecutionLane } from "../runtime-caps-resolver.js";
|
|
26
26
|
import { applyRuntimeGovernance, stripDelegationTools } from "../runtime-governance.js";
|
|
27
27
|
import { HttpError, encodeCheckpointScope } from "../security.js";
|
|
28
|
-
import { memorySpecForRequest } from "../memory-scope.js";
|
|
28
|
+
import { memoryProjectKeyFor, memorySpecForRequest } from "../memory-scope.js";
|
|
29
29
|
import { singleMemberOffFieldIssue } from "../request-value-closure.js";
|
|
30
30
|
import { a2aForScenario, mcpForScenario } from "../config-center/facade.js";
|
|
31
31
|
import { normalizeAttachments, normalizeResilience, normalizeResumeAtMode, normalizeSuggestNextPrompts, promptProfileFromBody, resolveTaskLimits, retainBackgroundProcessesFromBody, taskAgentsSpecFragment, toolMaterializeStrategyFromBody, toolNameListFromBody } from "../spec-fields.js";
|
|
@@ -36,13 +36,19 @@ import { MAX_SETTINGS_OUTPUT_STYLE_CHARS, acceptAppendSystemPrompt, applyTaskSet
|
|
|
36
36
|
import { enableForkFromBody, normalizeRetainSubagentSessions, selfOrchestrationFromBody } from "../task-workflow.js";
|
|
37
37
|
import { redactSecrets } from "../trace/redact.js";
|
|
38
38
|
import { DeferredSandboxPathEnv, isSandboxPathAdjudicationLane, sandboxPathEnvSlots } from "./deferred-sandbox-path-env.js";
|
|
39
|
-
import { executionLaneHomeDir } from "../execution-lane-caps.js";
|
|
39
|
+
import { executionLaneCaps, executionLaneHomeDir, executionLaneOf } from "../execution-lane-caps.js";
|
|
40
40
|
import { effectiveMemoryPersistenceCapable } from "./memory-boundary.js";
|
|
41
41
|
import { memoryFaceMounted } from "../memory-scope.js";
|
|
42
42
|
export function createResolveSpec(ctx) {
|
|
43
43
|
const { config, logger, metrics, localRoot, scenarios, principalCaps, centerRuntimeCapsResolver, getCenterPrompts, getKeyResolver, taskAttachmentStore, perSessionCwd, setSessionCwd, setSessionShellEnv, fenceSessionOwner, hookLlm, hookAgent, fleetBus, hookWakeBus, noteSessionShellGate, resumeAnchorStore, ownerAware, taskLimitCaps, taskTimeoutSec, selectEnvTool, sendUserFileToolSpec, memoryEngine, durableEnabled, approvalExemptionStore, singleUserAutoAcceptBaseline, checkpointStore, deploymentHooks, imageIndex, perTaskImage, sessionEnvSelection, liveQuestionFace, approverSeat, lockedKeys, } = ctx;
|
|
44
44
|
assertGuardPatternsUsable(config);
|
|
45
45
|
const onlySensitiveBaseline = buildOnlySensitiveBaselineWarning(config, { durableEnabled, singleUserAutoAcceptBaseline });
|
|
46
|
+
const realTaskRootOf = (auth) => {
|
|
47
|
+
if (isSandboxPathAdjudicationLane(config.remoteExec?.provider))
|
|
48
|
+
return undefined;
|
|
49
|
+
const sessionCwd = auth?.sessionId ? effectiveHostWorkspace(perSessionCwd.get(auth.sessionId), {}) : undefined;
|
|
50
|
+
return sessionCwd ?? (config.remoteExec === undefined ? process.cwd() : undefined);
|
|
51
|
+
};
|
|
46
52
|
if (onlySensitiveBaseline)
|
|
47
53
|
logger.warn(onlySensitiveBaseline.event, onlySensitiveBaseline.fields);
|
|
48
54
|
const resolveSpec = async (body, req, auth, opts) => {
|
|
@@ -88,7 +94,7 @@ export function createResolveSpec(ctx) {
|
|
|
88
94
|
};
|
|
89
95
|
const gateScenarioAndAppend = async (body, auth, opts) => {
|
|
90
96
|
const requested = gateScenarioRequest(await principalCaps?.scenarioRuling(auth?.principal), body.scenario, config.defaultScenario, Object.keys(scenarios), logger);
|
|
91
|
-
gateExecutionLane(await principalCaps?.executionRuling(auth?.principal), config.remoteExec?.provider
|
|
97
|
+
gateExecutionLane(await principalCaps?.executionRuling(auth?.principal), executionLaneOf(config.remoteExec?.provider), logger);
|
|
92
98
|
const scenarioName = scenarios[requested] ? requested : "default";
|
|
93
99
|
const cap = selectScenario(scenarios, scenarioName)(body, auth?.principal, auth?.sessionId !== undefined ? { sessionId: auth.sessionId } : {});
|
|
94
100
|
const centerDecls = getCenterPrompts()?.declarations;
|
|
@@ -144,7 +150,7 @@ export function createResolveSpec(ctx) {
|
|
|
144
150
|
const bindSettingsCwdEnvAndModel = (body, auth, gated, effMode, opts) => {
|
|
145
151
|
const { objective, parsedSettings } = gated;
|
|
146
152
|
const cwdWriteGate = cwdHonored(config) || deviceCwdHonored(config);
|
|
147
|
-
const execLane = config.remoteExec?.provider
|
|
153
|
+
const execLane = executionLaneOf(config.remoteExec?.provider);
|
|
148
154
|
if (auth?.sessionId)
|
|
149
155
|
fenceSessionOwner(auth.sessionId, auth.principal ?? null);
|
|
150
156
|
if (typeof body.cwd === "string" && body.cwd.length > 0 && auth?.sessionId) {
|
|
@@ -391,7 +397,7 @@ export function createResolveSpec(ctx) {
|
|
|
391
397
|
})(),
|
|
392
398
|
...(config.requirePrincipal !== true ? { backgroundScope: "session" } : {}),
|
|
393
399
|
memory: memoryEngine
|
|
394
|
-
? memorySpecForRequest(auth?.memoryScope, body.memoryWrite, s4DefaultScopes, { multiTenant: config.requirePrincipal === true }, { memory: body.memory, memoryCapture: body.memoryCapture })
|
|
400
|
+
? memorySpecForRequest(auth?.memoryScope, memoryProjectKeyFor(config, auth?.memoryScope, realTaskRootOf(auth)), body.memoryWrite, s4DefaultScopes, { multiTenant: config.requirePrincipal === true }, { memory: body.memory, memoryCapture: body.memoryCapture })
|
|
395
401
|
: undefined,
|
|
396
402
|
...((v) => (v !== undefined ? { memoryPersistenceCapable: v } : {}))(effectiveMemoryPersistenceCapable(config)),
|
|
397
403
|
tools: ((base) => {
|
|
@@ -450,8 +456,7 @@ export function createResolveSpec(ctx) {
|
|
|
450
456
|
};
|
|
451
457
|
const pathAdjudication = hostSemanticsLane
|
|
452
458
|
? (() => {
|
|
453
|
-
const
|
|
454
|
-
const realRoot = sessionCwd ?? (config.remoteExec === undefined ? process.cwd() : undefined);
|
|
459
|
+
const realRoot = realTaskRootOf(auth);
|
|
455
460
|
const gateCwd = realRoot ?? join(config.localDataRoot ?? localRoot, "fs-write-gate-unrooted");
|
|
456
461
|
return {
|
|
457
462
|
env: new NodeExecutionEnv({ cwd: gateCwd }),
|
|
@@ -558,7 +563,7 @@ export function createResolveSpec(ctx) {
|
|
|
558
563
|
handsReadOnly: governed.handsReadOnly === true,
|
|
559
564
|
excludeAllTools: governed.excludeAllTools === true,
|
|
560
565
|
excludeTools: governed.excludeTools,
|
|
561
|
-
|
|
566
|
+
...buildNoticeLaneFacts(executionLaneOf(config.remoteExec?.provider)),
|
|
562
567
|
})) {
|
|
563
568
|
governed = { ...governed, promptProvider: withNoPersistentMemoryNotice(governed.promptProvider) };
|
|
564
569
|
}
|
|
@@ -619,7 +624,7 @@ export function createResolveSpec(ctx) {
|
|
|
619
624
|
const isolatedExecEnv = isIsolatedExecEnv(config.remoteExec?.provider, config.remoteExec?.provider === "k8s" ? config.remoteExec.runtimeClass : undefined);
|
|
620
625
|
const decision = routeServiceTask({
|
|
621
626
|
isolatedExecEnv,
|
|
622
|
-
hasExecutionEnv: config.remoteExec
|
|
627
|
+
hasExecutionEnv: executionLaneCaps(executionLaneOf(config.remoteExec?.provider)).coreRemoteExecutionEnv === "supported",
|
|
623
628
|
...(config.autonomy ? { autonomy: config.autonomy } : {}),
|
|
624
629
|
explicitTeam: body.council === true || body.debate === true || scenarioName === "discuss",
|
|
625
630
|
});
|
|
@@ -191,7 +191,8 @@ export interface RunnerDepsCtx {
|
|
|
191
191
|
sessionPolicyStore: ReturnType<StoreBackend["sessionPolicy"]> | undefined;
|
|
192
192
|
runtimeCapsResolver: RunnerDeps["runtimeCapsResolver"];
|
|
193
193
|
/** [ref] per-edited-file rewind history (core `RunnerDeps.fileHistoryStore`; replaces the retired E19
|
|
194
|
-
* whole-tree snapshot seat — core 94632197 renamed the seat, not a coexistence). WIRING IS THE OPT-IN.
|
|
194
|
+
* whole-tree snapshot seat — core 94632197 renamed the seat, not a coexistence). WIRING IS THE OPT-IN.
|
|
195
|
+
* S-589:值 = `assembleFileHistory` 的捕获脸(后端 ∧ `FILE_HISTORY_CAPTURE`)。 */
|
|
195
196
|
fileHistoryStore: ReturnType<StoreBackend["fileHistory"]> | undefined;
|
|
196
197
|
/** [ref] 车二:持久化权限规则店 provider(core `RunnerDeps.permissionRuleStore`)。缺席 ⇒ 引擎的
|
|
197
198
|
* `permissionRules.storeWired` 如实报 false、`AskRequest.ruleOffers` 不铸(诚实缺席)。 */
|
|
@@ -5,6 +5,7 @@ import type { WorkflowCompletionInbox } from "../orchestration/workflow-completi
|
|
|
5
5
|
import { PlanCacheProbe } from "../plan-cache-probe.js";
|
|
6
6
|
import type { CheckpointStoreFull, StoreBackend, ToolResultStoreFull } from "../plugins/store-backend.js";
|
|
7
7
|
import type { TaskAttachmentStore } from "../plugins/task-attachment-store.js";
|
|
8
|
+
import type { FileHistoryErasureFace } from "../file-history-capture.js";
|
|
8
9
|
import type { OwnerAwareSessionStore } from "../security.js";
|
|
9
10
|
import type { DeviceStore } from "../device-store.js";
|
|
10
11
|
import { SessionWatchRegistry } from "../session-watch.js";
|
|
@@ -25,7 +26,9 @@ export interface SessionFacesCtx {
|
|
|
25
26
|
approvalExemptionStore: ReturnType<StoreBackend["approvalExemption"]> | undefined;
|
|
26
27
|
sessionPolicyStore: ReturnType<StoreBackend["sessionPolicy"]> | undefined;
|
|
27
28
|
taskAttachmentStore: TaskAttachmentStore | undefined;
|
|
28
|
-
|
|
29
|
+
/** S-589:文件历史的**擦除脸**(后端在即在,与 `FILE_HISTORY_CAPTURE` 无关;只有删除类动词)。E21 删除读它,
|
|
30
|
+
* 不读捕获脸 —— 关掉捕获的部署照样要删得掉已捕获的文件字节(旋钮只管写入,从不管擦除)。 */
|
|
31
|
+
fileHistoryErasure: FileHistoryErasureFace | undefined;
|
|
29
32
|
workflowCompletionInbox: WorkflowCompletionInbox | undefined;
|
|
30
33
|
/** [ref]:会话级任务清单车道(E21 级联的一条腿)。缺席 = 装配未接本车道 ⇒ 无清单可删。 */
|
|
31
34
|
taskListLane: TaskListLane | undefined;
|
|
@@ -6,7 +6,7 @@ import { setLeafAdvanceListener } from "../session-leaf-bus.js";
|
|
|
6
6
|
import { SessionWatchRegistry, posIntEnv } from "../session-watch.js";
|
|
7
7
|
import { defaultTaskRegistry, peerSessionBoxHandle } from "@sema-agent/core";
|
|
8
8
|
export function createSessionFaces(ctx) {
|
|
9
|
-
const { config, logger, metrics, localRoot, backend, sessionStore, runStore, checkpointStore, toolResultStore, resumeAnchorStore, approvalExemptionStore, sessionPolicyStore, taskAttachmentStore,
|
|
9
|
+
const { config, logger, metrics, localRoot, backend, sessionStore, runStore, checkpointStore, toolResultStore, resumeAnchorStore, approvalExemptionStore, sessionPolicyStore, taskAttachmentStore, fileHistoryErasure, workflowCompletionInbox, taskListLane, deviceStore, dropSessionScoped, mailboxStore, mailboxRecipientLifecycle, } = ctx;
|
|
10
10
|
const mysqlPool = backend?.mysqlPool();
|
|
11
11
|
const auditPgPool = backend?.pgPool();
|
|
12
12
|
const auditLocalRoot = backend?.kind === "local" ? (config.localDataRoot ?? localRoot) : undefined;
|
|
@@ -66,11 +66,11 @@ export function createSessionFaces(ctx) {
|
|
|
66
66
|
if (deviceStore)
|
|
67
67
|
await deviceStore.deleteByRootSession(sessionId);
|
|
68
68
|
dropSessionScoped?.(sessionId);
|
|
69
|
-
if (
|
|
70
|
-
if (typeof
|
|
71
|
-
await
|
|
69
|
+
if (fileHistoryErasure) {
|
|
70
|
+
if (typeof fileHistoryErasure.deleteBySession === "function")
|
|
71
|
+
await fileHistoryErasure.deleteBySession(sessionId);
|
|
72
72
|
else {
|
|
73
|
-
await
|
|
73
|
+
await fileHistoryErasure.reap(sessionId, []);
|
|
74
74
|
logger.warn("session_file_history_baselines_retained", {
|
|
75
75
|
sessionId,
|
|
76
76
|
note: "the local file-history store has no whole-scope purge verb; boundaries were reaped but v1 baselines (original file bytes) remain under the data root until the upstream purge seam lands — recorded as an open deletion-rights gap, not silent",
|
|
@@ -9,6 +9,7 @@ export declare function runStage04(ctx: Awaited<ReturnType<typeof runStage03>>):
|
|
|
9
9
|
prevStreak: number;
|
|
10
10
|
error?: string;
|
|
11
11
|
}) => void;
|
|
12
|
+
fileHistoryErasure: import("../file-history-capture.js").FileHistoryErasureFace | undefined;
|
|
12
13
|
fileHistoryStore: import("../plugins/store-backend.js").ServiceFileHistoryStore | undefined;
|
|
13
14
|
fleetLease: import("../fleet-lease.js").FleetLeaseManager | undefined;
|
|
14
15
|
fleetUsage: import("../fleet-client.js").FleetUsageAccumulator | undefined;
|
|
@@ -27,7 +27,7 @@ export async function runStage04(ctx) {
|
|
|
27
27
|
if (adoptionBoot.scanned > 0 || adoptionBoot.error !== undefined) {
|
|
28
28
|
logger.info("adoption_boot_scan", { ...adoptionBoot });
|
|
29
29
|
}
|
|
30
|
-
const { brain, pricing, counterDegradeHook, costQuota, modelUsageTracker, promptManifestTracker, fleetUsage, fleetLease, tracer, sideQueryAccounting, toolResultStore, sessionPolicyStore, fileHistoryStore, } = createBudgetAndTracing({ config, logger, metrics, backend, breakerState });
|
|
30
|
+
const { brain, pricing, counterDegradeHook, costQuota, modelUsageTracker, promptManifestTracker, fleetUsage, fleetLease, tracer, sideQueryAccounting, toolResultStore, sessionPolicyStore, fileHistoryStore, fileHistoryErasure, } = createBudgetAndTracing({ config, logger, metrics, backend, breakerState });
|
|
31
31
|
const permissionRuleStores = config.permissionRulesEnabled && backend ? backend.permissionRule() : undefined;
|
|
32
32
|
const permissionRuleProvider = permissionRuleStores
|
|
33
33
|
? createPermissionRuleStoreProvider({ durable: permissionRuleStores.durable })
|
|
@@ -44,6 +44,6 @@ export async function runStage04(ctx) {
|
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
46
|
await auditDormantPermissionRules({ stores: permissionRuleStores, logger, explicit: config.permissionRulesEnabledExplicit });
|
|
47
|
-
return { ...ctx, brain, costQuota, counterDegradeHook, fileHistoryStore, fleetLease, fleetUsage, memoryBundleFaces, memoryComplianceFaces, memoryOriginFaces, modelUsageTracker, permissionRuleProvider, permissionRuleStores, pricing, promptManifestTracker, ruleConsent, sessionMemoryStatusFace, sessionPolicyStore, sideQueryAccounting, toolResultStore, tracer };
|
|
47
|
+
return { ...ctx, brain, costQuota, counterDegradeHook, fileHistoryErasure, fileHistoryStore, fleetLease, fleetUsage, memoryBundleFaces, memoryComplianceFaces, memoryOriginFaces, modelUsageTracker, permissionRuleProvider, permissionRuleStores, pricing, promptManifestTracker, ruleConsent, sessionMemoryStatusFace, sessionPolicyStore, sideQueryAccounting, toolResultStore, tracer };
|
|
48
48
|
}
|
|
49
49
|
//# sourceMappingURL=stage-04-stores.js.map
|
|
@@ -22,6 +22,7 @@ export declare function runStage05(ctx: Awaited<ReturnType<typeof runStage04>>):
|
|
|
22
22
|
prevStreak: number;
|
|
23
23
|
error?: string;
|
|
24
24
|
}) => void;
|
|
25
|
+
fileHistoryErasure: import("../file-history-capture.js").FileHistoryErasureFace | undefined;
|
|
25
26
|
fileHistoryStore: import("../plugins/store-backend.js").ServiceFileHistoryStore | undefined;
|
|
26
27
|
fleetLease: import("../fleet-lease.js").FleetLeaseManager | undefined;
|
|
27
28
|
fleetUsage: import("../fleet-client.js").FleetUsageAccumulator | undefined;
|
|
@@ -83,6 +83,7 @@ export declare function runStage06(ctx: Awaited<ReturnType<typeof runStage05>>):
|
|
|
83
83
|
prevStreak: number;
|
|
84
84
|
error?: string;
|
|
85
85
|
}) => void;
|
|
86
|
+
fileHistoryErasure: import("../file-history-capture.js").FileHistoryErasureFace | undefined;
|
|
86
87
|
fileHistoryStore: import("../plugins/store-backend.js").ServiceFileHistoryStore | undefined;
|
|
87
88
|
fleetLease: import("../fleet-lease.js").FleetLeaseManager | undefined;
|
|
88
89
|
fleetUsage: import("../fleet-client.js").FleetUsageAccumulator | undefined;
|
|
@@ -98,6 +98,7 @@ export declare function runStage07(ctx: Awaited<ReturnType<typeof runStage06>>):
|
|
|
98
98
|
prevStreak: number;
|
|
99
99
|
error?: string;
|
|
100
100
|
}) => void;
|
|
101
|
+
fileHistoryErasure: import("../file-history-capture.js").FileHistoryErasureFace | undefined;
|
|
101
102
|
fileHistoryStore: import("../plugins/store-backend.js").ServiceFileHistoryStore | undefined;
|
|
102
103
|
fleetLease: import("../fleet-lease.js").FleetLeaseManager | undefined;
|
|
103
104
|
fleetUsage: import("../fleet-client.js").FleetUsageAccumulator | undefined;
|
|
@@ -6,9 +6,9 @@ import { parseCapEnv, parseNumOrFailNonNegative } from "../config.js";
|
|
|
6
6
|
import { ensureChildSessionDurableWithPromotion } from "../plugins/session-store.js";
|
|
7
7
|
import { webSearchConfigFromEnv, createWebSearchBackend, shouldProbeWebSearchOnBoot } from "../plugins/web-search.js";
|
|
8
8
|
import { createAuthorizer } from "../security.js";
|
|
9
|
-
import { assertGateIntentServiceable, buildForceDurableGateInertNotice, hasOperatorGateIntent } from "../approval.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
9
|
+
import { assertGateIntentServiceable, buildForceDurableGateInertNotice, buildNoResponderBootWarns, hasOperatorGateIntent } from "../approval.js";
|
|
10
|
+
import { executionLaneOf } from "../execution-lane-caps.js";
|
|
11
|
+
import { loadDeploymentSkills } from "../capabilities/skills.js";
|
|
12
12
|
import { createRepoClient } from "../capabilities/repo-tools.js";
|
|
13
13
|
import { buildScenarios, builtinScenarioDetails } from "../capabilities/scenarios.js";
|
|
14
14
|
import { RateLimiter } from "../observability/rate-limit.js";
|
|
@@ -73,16 +73,12 @@ export async function runStage07(ctx) {
|
|
|
73
73
|
tasksUsable: runStore !== undefined,
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
logger.warn("workflow_gate_no_responder", {
|
|
83
|
-
hint: "self-orchestration with no approval face: permissionMode default/auto/acceptEdits run_workflow asks will auto-deny (fail-closed); wire TOOL_APPROVAL_ENABLED=true or DURABLE_APPROVAL=true to answer them",
|
|
84
|
-
});
|
|
85
|
-
}
|
|
76
|
+
for (const w of buildNoResponderBootWarns({
|
|
77
|
+
lane: executionLaneOf(config.remoteExec?.provider),
|
|
78
|
+
selfOrchestrationEnabled: config.selfOrchestrationEnabled,
|
|
79
|
+
approvalFaceWired: toolApproval !== undefined || durableEnabled,
|
|
80
|
+
}))
|
|
81
|
+
logger.warn(w.event, w.fields);
|
|
86
82
|
if (singleUserAutoAcceptBaseline) {
|
|
87
83
|
logger.info("tool_policy_single_user_default", {
|
|
88
84
|
posture: "adjudicated auto-accept — ALL write/hand/MCP tool surfaces auto-allowed (core per-surface UNGATED enumeration suppressed for single-user turnkey)",
|
|
@@ -110,7 +106,7 @@ export async function runStage07(ctx) {
|
|
|
110
106
|
? backend.rateLimiter(config.rateLimitPerMin, counterDegradeHook).startRefresh()
|
|
111
107
|
: new RateLimiter(config.rateLimitPerMin);
|
|
112
108
|
bindRateLimiter(rateLimiter);
|
|
113
|
-
let skills =
|
|
109
|
+
let skills = loadDeploymentSkills(config);
|
|
114
110
|
skills = await configCenter.applyCenterCapabilities(skills);
|
|
115
111
|
const repoClient = config.gitApiBaseUrl ? createRepoClient(config.gitApiKind, config.gitApiBaseUrl, config.gitApiToken) : undefined;
|
|
116
112
|
const webSearchCfg = webSearchConfigFromEnv();
|
|
@@ -109,10 +109,9 @@ export declare function runStage08(ctx: Awaited<ReturnType<typeof runStage07>>):
|
|
|
109
109
|
kind: string;
|
|
110
110
|
streak: number;
|
|
111
111
|
prevStreak: number;
|
|
112
|
-
error
|
|
113
|
-
/** 租约 TTL = 2× sweep 间隔(§3)。抢租与每 domain 的续租共用同一个值 —— 两处手抄迟早只改一处。 */
|
|
114
|
-
?: string;
|
|
112
|
+
error?: string;
|
|
115
113
|
}) => void;
|
|
114
|
+
fileHistoryErasure: import("../file-history-capture.js").FileHistoryErasureFace | undefined;
|
|
116
115
|
fileHistoryStore: import("../plugins/store-backend.js").ServiceFileHistoryStore | undefined;
|
|
117
116
|
fleetLease: import("../fleet-lease.js").FleetLeaseManager | undefined;
|
|
118
117
|
fleetUsage: import("../fleet-client.js").FleetUsageAccumulator | undefined;
|
|
@@ -5,10 +5,10 @@ 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, costQuota,
|
|
8
|
+
const { approvalNonceStore, backend, backgroundAgentStore, ceilingVerdict, checkpointStore, config, configCenter, costQuota, fileHistoryErasure, handslessRunner, handslessSubRunner, hookAgentRunner, imageBakes, instanceId, localRoot, logger, mailboxStore, metrics, permissionRuleStores, pricing, rateLimiter, retentionExecutor, retentionLaneStore, rosterStore, runStore, runner, runnerTierFrozen, sqlWorkflowRunStore, subRunner, taskAttachmentStore, toolApproval, toolResultStore, workflowJournalStore, workflowNotifyGate, workflowNotifyJournal, workflowRecoverOpts, worktreeReap } = ctx;
|
|
9
9
|
const reaper = startReapers({
|
|
10
10
|
config, logger, metrics, localRoot, backend, subRunner, runStore, checkpointStore,
|
|
11
|
-
rateLimiter, costQuota, toolResultStore,
|
|
11
|
+
rateLimiter, costQuota, toolResultStore, fileHistoryErasure, taskAttachmentStore, imageBakes, worktreeReap,
|
|
12
12
|
workflowNotifyGate, workflowRecoverOpts, workflowJournalStore, sqlWorkflowRunStore, workflowNotifyJournal, rosterStore,
|
|
13
13
|
backgroundAgentStore, mailboxStore, toolApproval, permissionRuleStores, approvalNonceStore,
|
|
14
14
|
getRunDenySweep: () => runDenySweep,
|
|
@@ -145,6 +145,7 @@ export declare function runStage09(ctx: Awaited<ReturnType<typeof runStage08>>):
|
|
|
145
145
|
prevStreak: number;
|
|
146
146
|
error?: string;
|
|
147
147
|
}) => void;
|
|
148
|
+
fileHistoryErasure: import("../file-history-capture.js").FileHistoryErasureFace | undefined;
|
|
148
149
|
fileHistoryStore: import("../plugins/store-backend.js").ServiceFileHistoryStore | undefined;
|
|
149
150
|
fleetLease: import("../fleet-lease.js").FleetLeaseManager | undefined;
|
|
150
151
|
fleetUsage: import("../fleet-client.js").FleetUsageAccumulator | undefined;
|
|
@@ -6,12 +6,12 @@ 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, brain, checkpointStore, config, configCenter, deviceLane, dropSessionScoped, durableEnabled, executionEnvFactory,
|
|
9
|
+
const { approvalExemptionStore, backend, 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;
|
|
10
10
|
const { ownerAware, sessionAudit, sessionWatchRegistry, purgeSession, instrumentDegenerate, planCacheProbe } = createSessionFaces({
|
|
11
11
|
deviceStore: deviceLane?.store,
|
|
12
12
|
dropSessionScoped,
|
|
13
13
|
config, logger, metrics, localRoot, backend, sessionStore, runStore, checkpointStore, toolResultStore,
|
|
14
|
-
resumeAnchorStore, approvalExemptionStore, sessionPolicyStore, taskAttachmentStore,
|
|
14
|
+
resumeAnchorStore, approvalExemptionStore, sessionPolicyStore, taskAttachmentStore, fileHistoryErasure,
|
|
15
15
|
workflowCompletionInbox, taskListLane, mailboxStore, mailboxRecipientLifecycle,
|
|
16
16
|
});
|
|
17
17
|
const leaderEndpoint = createLeaderFace({ config, logger, brain, pricing, executionEnvFactory, toolResultStore, sessionStore, checkpointStore, governanceSeams, backend, tracer, usageWindowStore, promptSource: configCenter.promptSource, onError: runnerDeps.onError });
|
|
@@ -145,6 +145,7 @@ export declare function runStage10(ctx: Awaited<ReturnType<typeof runStage09>>):
|
|
|
145
145
|
prevStreak: number;
|
|
146
146
|
error?: string;
|
|
147
147
|
}) => void;
|
|
148
|
+
fileHistoryErasure: import("../file-history-capture.js").FileHistoryErasureFace | undefined;
|
|
148
149
|
fileHistoryStore: import("../plugins/store-backend.js").ServiceFileHistoryStore | undefined;
|
|
149
150
|
fleetLease: import("../fleet-lease.js").FleetLeaseManager | undefined;
|
|
150
151
|
fleetUsage: import("../fleet-client.js").FleetUsageAccumulator | undefined;
|
package/dist/boot/stores.js
CHANGED
|
@@ -32,7 +32,7 @@ import { assertSchemaMatchesCode } from "../plugins/schema-consistency.js";
|
|
|
32
32
|
import { assertCheckpointColumnSchema } from "../plugins/checkpoint-store-sql.js";
|
|
33
33
|
import { assertFileHistorySchema } from "../plugins/file-history-store-sql.js";
|
|
34
34
|
import { resolveStreamApprovalGate } from "../tool-approval.js";
|
|
35
|
-
import { buildMemoryWriteBoundaryAudit, effectiveMemoryPersistenceCapable } from "./memory-boundary.js";
|
|
35
|
+
import { buildMemoryBoundaryLaneFacts, buildMemoryWriteBoundaryAudit, effectiveMemoryPersistenceCapable } from "./memory-boundary.js";
|
|
36
36
|
import { buildMemoryPosture } from "../memory-posture.js";
|
|
37
37
|
import { establishSqlEnginePosture } from "../sql-engine-posture.js";
|
|
38
38
|
import { buildDisplaySafeUrl } from "../trace/redact.js";
|
|
@@ -194,25 +194,19 @@ export async function openStores(ctx) {
|
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
196
|
{
|
|
197
|
-
const
|
|
198
|
-
const hostSemanticsLane = lane === undefined || lane === "host";
|
|
199
|
-
const coreRemoteExecutionEnv = config.remoteExec !== undefined;
|
|
200
|
-
const containmentRoots = lane === undefined ? [process.cwd()] : [];
|
|
197
|
+
const laneFacts = buildMemoryBoundaryLaneFacts(config, process.cwd());
|
|
201
198
|
const memoryMountRoot = memoryEngine ? memoryMountRootOf(memoryEngine.backend, memoryEngine.root) : undefined;
|
|
202
199
|
const audit = buildMemoryWriteBoundaryAudit({
|
|
203
200
|
memoryRoot: memoryMountRoot,
|
|
204
|
-
|
|
205
|
-
hostSemanticsLane,
|
|
206
|
-
coreRemoteExecutionEnv,
|
|
201
|
+
...laneFacts,
|
|
207
202
|
declaredCapable: effectiveMemoryPersistenceCapable(config),
|
|
208
|
-
containmentRoots,
|
|
209
203
|
engineBackend: config.memoryEngineBackend,
|
|
210
204
|
});
|
|
211
205
|
for (const w of audit.warnings)
|
|
212
|
-
logger.warn(w.tag, { detail: w.detail, lane: lane
|
|
206
|
+
logger.warn(w.tag, { detail: w.detail, lane: laneFacts.lane, root: memoryMountRoot ?? null });
|
|
213
207
|
if (config.memoryPersistenceCapable === undefined && effectiveMemoryPersistenceCapable(config) === true) {
|
|
214
208
|
logger.info?.("memory_persistence_capable_auto_declared", {
|
|
215
|
-
lane: lane
|
|
209
|
+
lane: laneFacts.lane,
|
|
216
210
|
detail: "REMOTE_EXEC=host: file tools run on this machine's filesystem, so the assembler declares memoryPersistenceCapable=true (the core-side remote-env withhold would otherwise silently drop the memory WRITE instruction on this lane). Override with MEMORY_PERSISTENCE_CAPABLE=true|false.",
|
|
217
211
|
});
|
|
218
212
|
}
|
package/dist/brain.js
CHANGED
|
@@ -2,7 +2,8 @@ import { adjudicateModelRoute, createAnthropicBrain, createCircuitBreakerBrain,
|
|
|
2
2
|
import { routeKeyOf } from "@sema-agent/core";
|
|
3
3
|
import { buildDefaultResilience } from "./config-types.js";
|
|
4
4
|
import { resolveModelApiKey } from "./key-resolver.js";
|
|
5
|
-
import {
|
|
5
|
+
import { dispatchBrainLane } from "./model-provider.js";
|
|
6
|
+
import { openaiRouteBaseUrl } from "./model-route-endpoint.js";
|
|
6
7
|
import { buildDisplaySafeRefusal, buildDisplaySafeUrl } from "./trace/redact.js";
|
|
7
8
|
function isOffDeploymentRoot(baseUrl, config) {
|
|
8
9
|
if (!baseUrl)
|
|
@@ -10,11 +11,17 @@ function isOffDeploymentRoot(baseUrl, config) {
|
|
|
10
11
|
const entry = routeKeyOf(baseUrl);
|
|
11
12
|
if (entry === "")
|
|
12
13
|
return false;
|
|
13
|
-
return !
|
|
14
|
+
return !deploymentGatewayRoots(config).some((u) => routeKeyOf(u) === entry);
|
|
15
|
+
}
|
|
16
|
+
function deploymentGatewayRoots(config) {
|
|
17
|
+
return config.gatewayBaseUrl !== undefined ? [config.gatewayBaseUrl, ...config.gatewayFallbackUrls] : [];
|
|
18
|
+
}
|
|
19
|
+
function deploymentGatewayKey(config) {
|
|
20
|
+
return config.gatewayBaseUrl !== undefined ? config.gatewayApiKey : undefined;
|
|
14
21
|
}
|
|
15
22
|
function degradeDeclaredRoot(fallbackBaseUrl, config) {
|
|
16
|
-
const armed = Boolean(config
|
|
17
|
-
return armed ? config.gatewayBaseUrl : (fallbackBaseUrl
|
|
23
|
+
const armed = Boolean(deploymentGatewayKey(config)) && isOffDeploymentRoot(fallbackBaseUrl, config);
|
|
24
|
+
return armed ? config.gatewayBaseUrl : openaiRouteBaseUrl(fallbackBaseUrl, config.gatewayBaseUrl);
|
|
18
25
|
}
|
|
19
26
|
export const FAST_FAIL_MAX_RETRIES = 2;
|
|
20
27
|
function constructRouteBrain(label, sourceUrls, construct) {
|
|
@@ -41,12 +48,12 @@ export function createBrain(config, deps = {}) {
|
|
|
41
48
|
: fastFailTopology
|
|
42
49
|
? { maxRetries: FAST_FAIL_MAX_RETRIES }
|
|
43
50
|
: {};
|
|
44
|
-
const routes =
|
|
51
|
+
const routes = deploymentGatewayRoots(config);
|
|
45
52
|
const openaiBrains = routes.map((baseUrl, i) => {
|
|
46
53
|
const brain = constructRouteBrain(i === 0 ? "gateway route" : `gateway fallback route[${i - 1}]`, [baseUrl], () => createOpenAIBrain({
|
|
47
54
|
baseUrl,
|
|
48
55
|
get apiKey() {
|
|
49
|
-
return config
|
|
56
|
+
return deploymentGatewayKey(config);
|
|
50
57
|
},
|
|
51
58
|
...retryCap,
|
|
52
59
|
fetchImpl,
|
|
@@ -62,7 +69,11 @@ export function createBrain(config, deps = {}) {
|
|
|
62
69
|
})
|
|
63
70
|
: brain;
|
|
64
71
|
});
|
|
65
|
-
const gatewayBrain = openaiBrains.length
|
|
72
|
+
const gatewayBrain = openaiBrains.length === 0
|
|
73
|
+
? constructRouteBrain("openai route (no gateway declared)", [], () => createOpenAIBrain({ ...retryCap, fetchImpl, ...timeouts }))
|
|
74
|
+
: openaiBrains.length > 1
|
|
75
|
+
? createFailoverBrain(openaiBrains)
|
|
76
|
+
: openaiBrains[0];
|
|
66
77
|
const anthropicCfg = config.anthropic;
|
|
67
78
|
const anthropicBrain = anthropicCfg
|
|
68
79
|
? constructRouteBrain("anthropic route", [anthropicCfg.baseUrl], () => createAnthropicBrain({
|
|
@@ -86,9 +97,8 @@ export function createBrain(config, deps = {}) {
|
|
|
86
97
|
if (fallbackModel) {
|
|
87
98
|
const fbOwnApiKey = () => resolveModelApiKey(fallbackModel.name, config.modelApiKeyEnv ?? {}, process.env, config.modelApiKeys ?? {}) ??
|
|
88
99
|
resolveModelApiKey(degradeTo, config.modelApiKeyEnv ?? {}, process.env, config.modelApiKeys ?? {});
|
|
89
|
-
const
|
|
90
|
-
const
|
|
91
|
-
const fallback = fallbackLane === "anthropic" && anthropicBrain
|
|
100
|
+
const anthropicLaneHop = dispatchBrainLane(fallbackModel.provider, anthropicBrain !== undefined) === "anthropic";
|
|
101
|
+
const fallback = anthropicLaneHop && anthropicBrain
|
|
92
102
|
?
|
|
93
103
|
anthropicBrain
|
|
94
104
|
: constructRouteBrain(`degrade target "${degradeTo}"`, [fallbackModel.baseUrl, config.gatewayBaseUrl], () => createOpenAIBrain({
|
|
@@ -96,7 +106,7 @@ export function createBrain(config, deps = {}) {
|
|
|
96
106
|
return degradeDeclaredRoot(fallbackModel.baseUrl, config);
|
|
97
107
|
},
|
|
98
108
|
get apiKey() {
|
|
99
|
-
return config
|
|
109
|
+
return deploymentGatewayKey(config) || undefined;
|
|
100
110
|
},
|
|
101
111
|
...(config.gatewayMaxRetries !== undefined ? { maxRetries: config.gatewayMaxRetries } : {}),
|
|
102
112
|
fetchImpl,
|
|
@@ -129,8 +139,10 @@ export function brainSummary(config) {
|
|
|
129
139
|
const r = config.resilience ?? DEFAULT_RESILIENCE;
|
|
130
140
|
const hasFailover = config.gatewayFallbackUrls.length > 0;
|
|
131
141
|
const breakerActive = r.circuitBreaker && hasFailover;
|
|
142
|
+
const degradeTarget = config.degrade?.reactive ? config.models?.[config.degrade.to] : undefined;
|
|
143
|
+
const degradeEndpoint = degradeTarget ? openaiRouteBaseUrl(degradeTarget.baseUrl, config.gatewayBaseUrl) : undefined;
|
|
132
144
|
return {
|
|
133
|
-
gateway: buildDisplaySafeUrl(config.gatewayBaseUrl),
|
|
145
|
+
gateway: buildDisplaySafeUrl(config.gatewayBaseUrl ?? "") || null,
|
|
134
146
|
gatewayFallbacks: config.gatewayFallbackUrls.length,
|
|
135
147
|
failover: hasFailover,
|
|
136
148
|
anthropicRoute: Boolean(config.anthropic),
|
|
@@ -147,14 +159,12 @@ export function brainSummary(config) {
|
|
|
147
159
|
: "engine-default",
|
|
148
160
|
circuitBreakerNoop: r.circuitBreaker && !hasFailover ? "needs ≥2 gateway routes" : null,
|
|
149
161
|
reactiveDegradeTo: config.degrade?.reactive && config.models?.[config.degrade.to] ? config.degrade.to : null,
|
|
150
|
-
reactiveDegradeBaseUrl:
|
|
151
|
-
? buildDisplaySafeUrl(config.models[config.degrade.to].baseUrl || config.gatewayBaseUrl)
|
|
152
|
-
: null,
|
|
162
|
+
reactiveDegradeBaseUrl: buildDisplaySafeUrl(degradeEndpoint ?? "") || null,
|
|
153
163
|
...((() => {
|
|
154
164
|
const target = config.degrade?.reactive ? config.models?.[config.degrade.to] : undefined;
|
|
155
165
|
if (!target)
|
|
156
166
|
return { reactiveDegradeRoutePairing: null, reactiveDegradeRouteRefusal: null };
|
|
157
|
-
if (
|
|
167
|
+
if (dispatchBrainLane(target.provider, config.anthropic !== undefined) === "anthropic") {
|
|
158
168
|
return { reactiveDegradeRoutePairing: "anthropic-lane", reactiveDegradeRouteRefusal: null };
|
|
159
169
|
}
|
|
160
170
|
const declaresOwnCredential = config.modelApiKeyEnv?.[target.name] !== undefined ||
|
|
@@ -165,12 +175,12 @@ export function brainSummary(config) {
|
|
|
165
175
|
if (declaresOwnCredential) {
|
|
166
176
|
return { reactiveDegradeRoutePairing: "per-model-declared", reactiveDegradeRouteRefusal: null };
|
|
167
177
|
}
|
|
168
|
-
const verdict = adjudicateModelRoute({ id: target.id, baseUrl: target.baseUrl }, resolveRouteCredential(
|
|
178
|
+
const verdict = adjudicateModelRoute({ id: target.id, baseUrl: target.baseUrl }, resolveRouteCredential(((key) => (key ? { configApiKey: key } : {}))(deploymentGatewayKey(config))), { baseUrl: degradeDeclaredRoot(target.baseUrl, config) });
|
|
169
179
|
return verdict.ok
|
|
170
180
|
? { reactiveDegradeRoutePairing: `ok:${verdict.posture}`, reactiveDegradeRouteRefusal: null }
|
|
171
181
|
: {
|
|
172
182
|
reactiveDegradeRoutePairing: `broken:${verdict.code}`,
|
|
173
|
-
reactiveDegradeRouteRefusal: buildDisplaySafeRefusal(routeRefusalText(verdict), [target.baseUrl ?? "", degradeDeclaredRoot(target.baseUrl, config)]),
|
|
183
|
+
reactiveDegradeRouteRefusal: buildDisplaySafeRefusal(routeRefusalText(verdict), [target.baseUrl ?? "", degradeDeclaredRoot(target.baseUrl, config) ?? ""]),
|
|
174
184
|
};
|
|
175
185
|
})()),
|
|
176
186
|
};
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ExecutionLane, type RemoteExecProvider } from "../execution-lane-caps.js";
|
|
2
2
|
export interface ExecutionLaneCapability {
|
|
3
|
-
/** 本部署的执行车道词(闭集 = {@link
|
|
4
|
-
readonly provider:
|
|
3
|
+
/** 本部署的执行车道词(闭集 = {@link ExecutionLane} 八词;`REMOTE_EXEC` 未设 ⇒ `"in-process"`,见头注 S-602 段)。 */
|
|
4
|
+
readonly provider: ExecutionLane;
|
|
5
5
|
/** 工具跑的那台机器就是本进程这台吗(= server 盘上的绝对路径对模型的工具有没有意义)。
|
|
6
6
|
* 属主 = `task-cwd.ts` 的 {@link toolsRunOnThisHost},与 `skills[].baseDir` 的铸点同一只函数。 */
|
|
7
7
|
readonly toolsOnThisHost: boolean;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* 部署席 → 消费端窄投影。形照 `projectWebSearchCapability` / `projectSqlEngineCapability`:
|
|
11
|
-
*
|
|
11
|
+
* 不碰 config.ts(只从车道表模块取词与归一读口,那是叶),于是本模块是叶。
|
|
12
12
|
*
|
|
13
|
-
* 🔴
|
|
14
|
-
* {@link RemoteExecProvider} 的成员,配置联合里那条臂改名 ⇒ 本行当场 tsc 红(S-382 对三个 provider 词
|
|
15
|
-
* 免入表的同一条理由 —— 会静默漂的只有**本仓自铸**的词,这里一个都没有)。
|
|
13
|
+
* 🔴 本处**不写**任何缺席折词(S-602 门 D):缺席归一只在 {@link executionLaneOf} 一处。
|
|
16
14
|
*/
|
|
17
15
|
export declare function projectExecutionLaneCapability(config: {
|
|
18
16
|
readonly remoteExec?: {
|